import $ from '../../shared/dom7.js';
import { extend } from '../../shared/utils.js';
import History from '../../shared/history.js';
import asyncComponent from './async-component.js';
function tabLoad(tabRoute, loadOptions) {
  if (loadOptions === void 0) {
    loadOptions = {};
  }
  const router = this;
  const options = extend({
    animate: router.params.animate,
    browserHistory: true,
    history: true,
    parentPageEl: null,
    preload: false,
    on: {}
  }, loadOptions);
  let currentRoute;
  let previousRoute;
  if (options.route) {
    // Set Route
    if (!options.preload && options.route !== router.currentRoute) {
      previousRoute = router.previousRoute;
      router.currentRoute = options.route;
    }
    if (options.preload) {
      currentRoute = options.route;
      previousRoute = router.currentRoute;
    } else {
      currentRoute = router.currentRoute;
      if (!previousRoute) previousRoute = router.previousRoute;
    }

    // Update Browser History
    if (router.params.browserHistory && options.browserHistory && !options.reloadPrevious) {
      History[router.params.browserHistoryTabs](router.view.id, {
        url: options.route.url
      }, (router.params.browserHistoryRoot || '') + router.params.browserHistorySeparator + options.route.url);
    }

    // Update Router History
    if (options.history) {
      router.history[Math.max(router.history.length - 1, 0)] = options.route.url;
      router.saveHistory();
    }
  }

  // Show Tab
  const $parentPageEl = $(options.parentPageEl || router.currentPageEl);
  let tabEl;
  if ($parentPageEl.length && $parentPageEl.find(`#${tabRoute.id}`).length) {
    tabEl = $parentPageEl.find(`#${tabRoute.id}`).eq(0);
  } else if (router.view.selector) {
    tabEl = `${router.view.selector} #${tabRoute.id}`;
  } else {
    tabEl = `#${tabRoute.id}`;
  }
  const tabShowResult = router.app.tab.show({
    tabEl,
    animate: options.animate,
    tabRoute: options.route
  });
  const {
    $newTabEl,
    $oldTabEl,
    animated,
    onTabsChanged
  } = tabShowResult;
  if ($newTabEl && $newTabEl.parents('.page').length > 0 && options.route) {
    const tabParentPageData = $newTabEl.parents('.page')[0].f7Page;
    if (tabParentPageData && options.route) {
      tabParentPageData.route = options.route;
    }
  }

  // Tab Content Loaded
  function onTabLoaded(contentEl) {
    // Remove theme elements
    router.removeThemeElements($newTabEl);
    let tabEventTarget = $newTabEl;
    if (typeof contentEl !== 'string') tabEventTarget = $(contentEl);
    tabEventTarget.trigger('tab:init tab:mounted', tabRoute);
    router.emit('tabInit tabMounted', $newTabEl[0], tabRoute);
    if ($oldTabEl && $oldTabEl.length) {
      if (animated) {
        onTabsChanged(() => {
          router.emit('routeChanged', router.currentRoute, router.previousRoute, router);
          if (router.params.unloadTabContent) {
            router.tabRemove($oldTabEl, $newTabEl, tabRoute);
          }
        });
      } else {
        router.emit('routeChanged', router.currentRoute, router.previousRoute, router);
        if (router.params.unloadTabContent) {
          router.tabRemove($oldTabEl, $newTabEl, tabRoute);
        }
      }
    }
  }
  if ($newTabEl[0].f7RouterTabLoaded) {
    if (!$oldTabEl || !$oldTabEl.length) return router;
    if (animated) {
      onTabsChanged(() => {
        router.emit('routeChanged', router.currentRoute, router.previousRoute, router);
      });
    } else {
      router.emit('routeChanged', router.currentRoute, router.previousRoute, router);
    }
    return router;
  }

  // Load Tab Content
  function loadTab(loadTabParams, loadTabOptions) {
    // Load Tab Props
    const {
      url,
      content,
      el,
      component,
      componentUrl
    } = loadTabParams;
    // Component/Template Callbacks
    function resolve(contentEl) {
      router.allowPageChange = true;
      if (!contentEl) return;
      if (typeof contentEl === 'string') {
        $newTabEl.html(contentEl);
      } else {
        $newTabEl.html('');
        if (contentEl.f7Component) {
          contentEl.f7Component.mount(componentEl => {
            $newTabEl.append(componentEl);
          });
        } else {
          $newTabEl.append(contentEl);
        }
      }
      $newTabEl[0].f7RouterTabLoaded = true;
      onTabLoaded(contentEl);
    }
    function reject() {
      router.allowPageChange = true;
      return router;
    }
    if (content) {
      resolve(content);
    } else if (el) {
      resolve(el);
    } else if (component || componentUrl) {
      // Load from component (F7/Vue/React/...)
      try {
        router.tabComponentLoader({
          tabEl: $newTabEl[0],
          component,
          componentUrl,
          options: loadTabOptions,
          resolve,
          reject
        });
      } catch (err) {
        router.allowPageChange = true;
        throw err;
      }
    } else if (url) {
      // Load using XHR
      if (router.xhrAbortController) {
        router.xhrAbortController.abort();
        router.xhrAbortController = false;
      }
      router.xhrRequest(url, loadTabOptions).then(tabContent => {
        resolve(tabContent);
      }).catch(() => {
        router.allowPageChange = true;
      });
    }
  }
  let hasContentLoadProp;
  'url content component el componentUrl'.split(' ').forEach(tabLoadProp => {
    if (tabRoute[tabLoadProp]) {
      hasContentLoadProp = true;
      loadTab({
        [tabLoadProp]: tabRoute[tabLoadProp]
      }, options);
    }
  });

  // Async
  function asyncResolve(resolveParams, resolveOptions) {
    loadTab(resolveParams, extend(options, resolveOptions));
  }
  function asyncReject() {
    router.allowPageChange = true;
  }
  if (tabRoute.async) {
    tabRoute.async.call(router, {
      router,
      to: currentRoute,
      from: previousRoute,
      resolve: asyncResolve,
      reject: asyncReject,
      app: router.app
    });
  } else if (tabRoute.asyncComponent) {
    asyncComponent(router, tabRoute.asyncComponent, asyncResolve, asyncReject);
  } else if (!hasContentLoadProp) {
    router.allowPageChange = true;
  }
  return router;
}
function tabRemove($oldTabEl, $newTabEl, tabRoute) {
  const router = this;
  let hasTabComponentChild;
  if ($oldTabEl[0]) {
    $oldTabEl[0].f7RouterTabLoaded = false;
    delete $oldTabEl[0].f7RouterTabLoaded;
  }
  $oldTabEl.children().each(tabChild => {
    if (tabChild.f7Component) {
      hasTabComponentChild = true;
      $(tabChild).trigger('tab:beforeremove', tabRoute);
      tabChild.f7Component.destroy();
    }
  });
  if (!hasTabComponentChild) {
    $oldTabEl.trigger('tab:beforeremove', tabRoute);
  }
  router.emit('tabBeforeRemove', $oldTabEl[0], $newTabEl[0], tabRoute);
  router.removeTabContent($oldTabEl[0], tabRoute);
}
export { tabLoad, tabRemove };