<template>
  <div class="
    w-full h-[100dvh] overflow-hidden
    p-1 popup-lg:py-2 popup-lg:px-2 window:py-4 window:px-8
    flex flex-row justify-center items-center
  ">

    <!-- page content -->
    <div
      class="w-full  h-[100dvh] overflow-hidden flex flex-col"
      :class="{'max-w-[1920px]': !isDebugging}"
    >
      <PopupHead
        v-if="role === 'popup' && settings && siteSettings && eventBus"
        :settings="settings"
        :siteSettings="siteSettings"
        :site="site"
        :eventBus="eventBus"
      >
      </PopupHead>
      <div v-else>
        <h1 class="text-[3em] grow-0 shrink-0">Ultrawidify settings</h1>
      </div>

      <div v-if="!settingsInitialized" class="flex flex-row w-full justify-center items-center">
        Loading settings...
      </div>

      <SettingsWindowContent v-else
        class="grow shrink"
        :role="role"
        :initialPath="initialPath"
        :settings="settings"
        :eventBus="eventBus"
        :logger="logger"
        :inPlayer="false"
        :site="site"
        @debugStatusChanged="setDebugStatus"
      >
      </SettingsWindowContent>
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import BrowserDetect from '@src/ext/conf/BrowserDetect';
import { LogAggregator } from '@src/ext/lib/logging/LogAggregator';
import { ComponentLogger } from '@src/ext/lib/logging/ComponentLogger';
import Settings from '@src/ext/lib/settings/Settings';
import { SiteSettings } from '@src/ext/lib/settings/SiteSettings';
import SettingsWindowContent from '@components/SettingsWindowContent.vue';

import EventBus from '@src/ext/lib/EventBus';
import CommsClient, { CommsOrigin } from '@src/ext/lib/comms/CommsClient';
import {ChromeShittinessMitigations as CSM} from '@src/common/js/ChromeShittinessMitigations';

import PopupHead from '@components/PopupHead.vue';

export default defineComponent({
  components: {
    SettingsWindowContent,
    PopupHead,
  },
  data () {
    return {
      BrowserDetect,
      site: undefined,
      settings: undefined as Settings | undefined,
      siteSettings: undefined as SiteSettings | undefined,
      eventBus: undefined as EventBus | undefined,
      logger: undefined as ComponentLogger | undefined,
      logAggregator: undefined as LogAggregator | undefined,
      settingsInitialized: false,
      role: 'settings',
      initialPath: undefined as string[] | undefined,
      isDebugging: false,
    }
  },
  async created() {
    const [segment, ...path] = window.location.hash.split('/');
    this.initialPath = path;

    switch (segment) {
      case '#popup':
        await this.setupPopup();
        break;
      case '#iframe':
        await this.setupIframe();
        break;
      case '#settings':
      case '#updated':
      case '#installed':
      default:
        await this.setupSettingsPage(segment);
    }

    if (segment !== '#popup') {
      // undo that workaround that makes popup work correctly if we aren't in a popup
      document.getElementsByTagName('html')[0].setAttribute('style', '');
    }

    await this.settings.init();
    this.settingsInitialized = true;
  },
  methods: {
    setDebugStatus(isDebugging: boolean) {
      this.isDebugging = isDebugging;
    },
    updateConfig() {
      this.settings.init();
      this.$nextTick( () => this.$forceUpdate());
    },

    /**
     * Initializes page when it's being loaded from the settings
     */
    async setupSettingsPage(segment) {
      if (!segment) {
        this.role = 'settings';
      } else {
        this.role = segment.replace('#', '');
      }

      this.logAggregator = new LogAggregator('');
      this.logger = new ComponentLogger(this.logAggregator, 'App.vue');

      this.settings = new Settings({
        logAggregator: this.logAggregator,
        onSettingsChanged: () => this.updateConfig()
      });
    },

    /**
     * Initializes page when it's being loaded as extension popup
     */
    async setupPopup() {
      this.role = 'popup';
      try {
        this.logAggregator = new LogAggregator('🔵ext-popup🔵');
        this.logger = new ComponentLogger(this.logAggregator, 'Popup');

        this.settings = new Settings({afterSettingsSaved: () => this.updateConfig(), logAggregator: this.logAggregator});
        await this.settings.init();
        this.settingsInitialized = true;

        // const port = chrome.runtime.connect({name: 'popup-port'});
        // port.onMessage.addListener( (m,p) => this.processReceivedMessage(m,p));
        // CSM.setProperty('port', port);

        this.eventBus = new EventBus();
        this.eventBus.subscribe(
          'set-current-site',
          {
            source: this,
            function: (config, context) => {
              if (this.site) {
                if (!this.site.host) {
                  // dunno why this fix is needed, but sometimes it is
                  this.site.host = config.site.host;
                }
              }
              this.site = config.site;
              // this.selectedSite = this.selectedSite || config.site.host;
              this.siteSettings = this.settings.getSiteSettings({site: this.site.host});

              console.log('set-site received:', this.site, this.siteSettings, 'current path:', this.initialPath);
              if (!this.initialPath || this.initialPath.length < 1) {
                if (this.siteSettings.data.enable) {
                  this.initialPath = ['video-settings'];
                } else {
                  this.initialPath = ['site-extension-settings'];
                }
              }
              console.log('New path:', this.initialPath);


              this.eventBus.setupPopupTunnelWorkaround({
                origin: CommsOrigin.Popup,
                comms: {
                  forwardTo: 'active'
                }
              });

              this.loadHostnames();
              this.loadFrames();
            }
          },
        );
        this.eventBus.subscribe(
          'open-popup-settings',
          {
            source: this,
            function: (config) => {
              this.selectTab(config.tab)
            }
          }
        )

        this.comms = new CommsClient('popup-port', this.logger, this.eventBus);
        this.eventBus.setComms(this.comms);
        this.eventBus.setupPopupTunnelWorkaround({
          origin: CommsOrigin.Popup,
          comms: {forwardTo: 'active'}
        });


        // ensure we'll clean player markings on popup close
        window.addEventListener("unload", () => {
          CSM.port.postMessage({
            cmd: 'unmark-player',
            forwardToAll: true,
          });
          // if (BrowserDetect.anyChromium) {
          //   chrome.extension.getBackgroundPage().sendUnmarkPlayer({
          //     cmd: 'unmark-player',
          //     forwardToAll: true,
          //   });
          // }
        });

        // get info about current site from background script
        while (true) {
          this.requestSite();
          await this.sleep(5000);
        }
      } catch (e) {
        console.error('[Popup.vue::created()] An error happened:', e)
      }
    },

    /**
     * Initializes page when it's being loaded as in-page settings window
     */
    async setupIframe() {
      this.role='ui-window';

      this.logAggregator = new LogAggregator('settings-page');
      this.logger = new ComponentLogger(this.logAggregator, 'SettingsPage');

      this.settings = new Settings({
        logAggregator: this.logAggregator,
        onSettingsChanged: () => this.updateConfig()
      });

      if (this.defaultTab) {
        this.selectedTab = this.defaultTab;
      }
      this.siteSettings = this.settings.getSiteSettings({site: this.site});
      this.tabs.find(x => x.id === 'changelog').highlight = !this.settings.active?.whatsNewChecked;

      this.eventBus?.subscribe(
        'uw-show-ui',
        {
          source: this,
          function: () => {
            if (this.inPlayer) {
              return; // show-ui is only intended for global overlay
            }
          },
        }
      )
    },

    //#region EXTENSION POPUP

    showInPlayerUi() {
      this.eventBus.send('uw-set-ui-state', {globalUiVisible: true}, {comms: {forwardTo: 'active'}});
    },
    async sleep(t) {
      return new Promise<void>( (resolve,reject) => {
        setTimeout(() => resolve(), t);
      });
    },
    toObject(obj) {
      return JSON.parse(JSON.stringify(obj));
    },
    requestSite() {
      try {
        this.logger.log('info','popup', '[popup::getSite] Requesting current site ...')
        // CSM.port.postMessage({command: 'get-current-site'});
        this.eventBus.send(
          'get-current-site',
          {},
          {
            comms: {forwardTo: 'active'}
          }
        );
      } catch (e) {
        this.logger.log('error','popup','[popup::getSite] sending get-current-site failed for some reason. Reason:', e);
      }
    },
    getRandomColor() {
      return `rgb(${Math.floor(Math.random() * 128)}, ${Math.floor(Math.random() * 128)}, ${Math.floor(Math.random() * 128)})`;
    },
    selectTab(tab) {
      this.selectedTab = tab;
    },
    isDefaultFrame(frameId) {
      return frameId === '__playing' || frameId === '__all';
    },
    loadHostnames() {
      this.activeHosts = this.site.hostnames;
    },
    loadFrames() {
      this.activeFrames = [{
        host: this.site.host,
        isIFrame: false,  // not used tho. Maybe one day
      }];

      for (const frame in this.site.frames) {
        if (!this.activeFrames.find(x => x.host === this.site.frames[frame].host)) {
          this.activeFrames.push({
            id: `${this.site.id}-${frame}`,
            label: this.site.frames[frame].host,
            host: this.site.frames[frame].host,
            ...this.site.frames[frame],
            ...this.settings.active.sites[this.site.frames[frame].host]
          })
        };
      }
    },
    //#endregion
  }
});
</script>

