import { isWhitespace } from '@/utils/helper';
import BrowserAPIService from '@/service/browser-api/BrowserAPIService';

function handleEventListener(target, validate) {
  return (data, activeTab) => {
    return new Promise((resolve) => {
      let resolved = false;
      const eventListener = (event) => {
        if (resolved) return;
        if (validate && !validate(event, { data, activeTab })) return;

        target.removeListener(eventListener);
        resolve(event);
      };

      setTimeout(() => {
        resolved = true;
        target.removeListener(eventListener);
        resolve('');
      }, data.timeout || 10000);

      target.addListener(eventListener);
    });
  };
}

function onTabLoaded({ tabLoadedUrl, activeTabLoaded, timeout }, { id }) {
  return new Promise((resolve, reject) => {
    let resolved = false;

    const checkActiveTabStatus = () => {
      if (resolved) return;
      if (!id) {
        reject(new Error('no-tab'));
        return;
      }

      BrowserAPIService.tabs
        .get(id)
        .then((tab) => {
          if (tab.status === 'complete') {
            resolve();
            return;
          }

          setTimeout(checkActiveTabStatus, 1000);
        })
        .catch(reject);
    };

    const url = isWhitespace(tabLoadedUrl)
      ? '<all_urls>'
      : tabLoadedUrl.replace(/\s/g, '').split(',');
    const checkTabsStatus = () => {
      BrowserAPIService.tabs
        .query({
          url,
          status: 'loading',
        })
        .then((tabs) => {
          if (resolved) return;
          if (tabs.length === 0) {
            resolve();
            return;
          }

          setTimeout(checkTabsStatus, 1000);
        })
        .catch(reject);
    };

    if (activeTabLoaded) checkActiveTabStatus();
    else checkTabsStatus();

    setTimeout(() => {
      resolved = true;
      reject(new Error('timeout'));
    }, timeout || 10000);
  });
}

const validateCreatedTab = ({ url }, { data }) => {
  if (!isWhitespace(data.tabUrl)) {
    const regex = new RegExp(data.tabUrl, 'gi');

    if (!regex.test(url)) return false;
  }

  return true;
};
const events = {
  'tab:loaded': onTabLoaded,
  'tab:close': handleEventListener(BrowserAPIService.tabs.onRemoved),
  'tab:create': handleEventListener(
    BrowserAPIService.webNavigation.onCreatedNavigationTarget,
    validateCreatedTab
  ),
  'window:create': handleEventListener(
    BrowserAPIService.webNavigation.onCreatedNavigationTarget,
    validateCreatedTab
  ),
  'window:close': handleEventListener(BrowserAPIService.windows.onRemoved),
};

export default async function ({ data, id }) {
  const currentEvent = events[data.eventName];

  if (!currentEvent) {
    throw new Error(`Can't find ${data.eventName} event`);
  }

  const result = await currentEvent(data, this.activeTab);

  if (data.eventName === 'tab:create' && data.setAsActiveTab) {
    this.activeTab.id = result.tabId;
    this.activeTab.url = result.url;
  }

  return {
    data: result || '',
    nextBlockId: this.getBlockConnections(id),
  };
}
