/**
 * notion-enhancer: tabs
 * (c) 2021 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
 * (https://notion-enhancer.github.io/) under the MIT license
 */

'use strict';

module.exports = async function (api, db, __exports, __eval) {
  const url = require('url'),
    electron = require('electron'),
    electronWindow = electron.remote.getCurrentWindow(),
    { components, web } = api;

  window['__start'] = async () => {
    // display:none; to prevent content flash while css loads
    document.body.style.display = 'none';

    const tabCache = new Map(),
      Tab = await require('./tab.cjs')(api, db, tabCache);
    document.body.dataset.tabLabels = await db.get(['label_type']);
    document.body.dataset.tabStyle = await db.get(['layout_style']);

    const $header = web.html`<header></header>`,
      $tabs = web.html`<div id="tabs"></div>`,
      $newTab = web.html`<div class="new-tab">${await components.feather('plus')}</div>`,
      $root = document.querySelector('#root'),
      $windowActions = web.html`<div id="window-actions"></div>`;
    document.body.prepend(web.render($header, $tabs, $newTab, $windowActions));

    $newTab.addEventListener('click', () => new Tab($tabs, $root));
    electron.ipcRenderer.on('notion-enhancer:close-tab', (event, id) => {
      const tab = tabCache.get(id);
      if (tab) tab.close();
    });
    electron.ipcRenderer.on(
      'notion-enhancer:open-tab',
      (event, opts) => new Tab($tabs, $root, opts)
    );

    const rememberLastOpen = await db.get(['remember_last_open']),
      openTabs = await db.get(['last_open_tabs_cache']);
    if (rememberLastOpen && openTabs && Array.isArray(openTabs)) {
      for (const tab of openTabs) {
        new Tab($tabs, $root, { ...tab, cancelAnimation: true });
      }
    } else {
      new Tab($tabs, $root, {
        notionUrl: url.parse(window.location.href, true).query.path,
        cancelAnimation: true,
      });
    }
    window.addEventListener('beforeunload', () => {
      const openTabs = [...$tabs.children]
        .filter(($tab) => tabCache.get($tab.id))
        .map(($tab) => {
          const tab = tabCache.get($tab.id);
          return {
            notionUrl: tab.$notion.src,
            icon: tab.icon,
            title: tab.title,
          };
        });
      db.set(['last_open_tabs_cache'], openTabs);
    });

    let $draggedTab;
    const $dragIndicator = web.html`<span class="drag-indicator"></span>`,
      getDragTarget = ($el) => {
        while (!$el.matches('.tab, header, body')) $el = $el.parentElement;
        if ($el.matches('header')) $el = $el.firstElementChild;
        return $el.matches('#tabs, .tab') ? $el : undefined;
      },
      resetDraggedTabs = () => {
        if ($draggedTab) {
          $dragIndicator.remove();
          $draggedTab.style.opacity = '';
          $draggedTab = undefined;
        }
      };
    $header.addEventListener('dragstart', (event) => {
      $draggedTab = getDragTarget(event.target);
      $draggedTab.style.opacity = 0.5;
      const tab = tabCache.get($draggedTab.id);
      event.dataTransfer.setData(
        'text',
        JSON.stringify({
          window: electronWindow.webContents.id,
          tab: $draggedTab.id,
          icon: tab.$tabIcon.innerText || tab.$tabIcon.style.background,
          title: tab.$tabTitle.innerText,
          url: tab.$notion.src,
        })
      );
    });
    $header.addEventListener('dragover', (event) => {
      const $target = getDragTarget(event.target);
      if ($target) {
        if ($target.matches('#tabs')) {
          $target.after($dragIndicator);
        } else if ($target.matches('#tabs > :first-child')) {
          $tabs.before($dragIndicator);
        } else $target.before($dragIndicator);
        event.preventDefault();
      }
    });
    document.addEventListener('drop', (event) => {
      const eventData = JSON.parse(event.dataTransfer.getData('text')),
        $target = getDragTarget(event.target) || $tabs,
        sameWindow = eventData.window === electronWindow.webContents.id,
        tabMovement =
          !sameWindow ||
          ($target &&
            $target !== $draggedTab &&
            $target !== $draggedTab.nextElementSibling &&
            ($target.matches('#tabs') ? $target.lastElementChild !== $draggedTab : true));
      if (!sameWindow) {
        electron.ipcRenderer.send('notion-enhancer:close-tab', {
          window: eventData.window,
          id: eventData.tab,
        });
        const transferred = new Tab($tabs, $root, {
          notionUrl: eventData.url,
          cancelAnimation: true,
          icon: eventData.icon,
          title: eventData.title,
        });
        $draggedTab = transferred.$tab;
      }
      if (tabMovement) {
        if ($target.matches('#tabs')) {
          $target.append($draggedTab);
        } else $target.before($draggedTab);
      }
      resetDraggedTabs();
    });
    $header.addEventListener('dragend', (event) => resetDraggedTabs());
  };
};
