import { window, document } from 'ssr-window';
import $ from 'dom7';
import Utils from './utils';

const History = {
  queue: [],
  clearQueue() {
    if (History.queue.length === 0) return;
    const currentQueue = History.queue.shift();
    currentQueue();
  },
  routerQueue: [],
  clearRouterQueue() {
    if (History.routerQueue.length === 0) return;
    const currentQueue = History.routerQueue.pop();
    const { router, stateUrl, action } = currentQueue;

    let animate = router.params.animate;
    if (router.params.pushStateAnimate === false) animate = false;

    if (action === 'back') {
      router.back({ animate, pushState: false });
    }
    if (action === 'load') {
      router.navigate(stateUrl, { animate, pushState: false });
    }
  },
  handle(e) {
    if (History.blockPopstate) return;
    const app = this;
    // const mainView = app.views.main;
    let state = e.state;
    History.previousState = History.state;
    History.state = state;

    History.allowChange = true;
    History.clearQueue();

    state = History.state;
    if (!state) state = {};

    app.views.forEach((view) => {
      const router = view.router;
      let viewState = state[view.id];
      if (!viewState && view.params.pushState) {
        viewState = {
          url: view.router.history[0],
        };
      }
      if (!viewState) return;
      const stateUrl = viewState.url || undefined;

      let animate = router.params.animate;
      if (router.params.pushStateAnimate === false) animate = false;

      if (stateUrl !== router.url) {
        if (router.history.indexOf(stateUrl) >= 0) {
          // Go Back
          if (router.allowPageChange) {
            router.back({ animate, pushState: false });
          } else {
            History.routerQueue.push({
              action: 'back',
              router,
            });
          }
        } else if (router.allowPageChange) {
          // Load page
          router.navigate(stateUrl, { animate, pushState: false });
        } else {
          History.routerQueue.unshift({
            action: 'load',
            stateUrl,
            router,
          });
        }
      }
    });
  },
  initViewState(viewId, viewState) {
    const newState = Utils.extend({}, (History.state || {}), {
      [viewId]: viewState,
    });
    History.state = newState;
    window.history.replaceState(newState, '');
  },
  push(viewId, viewState, url) {
    if (!History.allowChange) {
      History.queue.push(() => {
        History.push(viewId, viewState, url);
      });
      return;
    }
    History.previousState = History.state;
    const newState = Utils.extend({}, (History.previousState || {}), {
      [viewId]: viewState,
    });
    History.state = newState;
    window.history.pushState(newState, '', url);
  },
  replace(viewId, viewState, url) {
    if (!History.allowChange) {
      History.queue.push(() => {
        History.replace(viewId, viewState, url);
      });
      return;
    }
    History.previousState = History.state;
    const newState = Utils.extend({}, (History.previousState || {}), {
      [viewId]: viewState,
    });
    History.state = newState;
    window.history.replaceState(newState, '', url);
  },
  go(index) {
    History.allowChange = false;
    window.history.go(index);
  },
  back() {
    History.allowChange = false;
    window.history.back();
  },
  allowChange: true,
  previousState: {},
  state: window.history.state,
  blockPopstate: true,
  init(app) {
    $(window).on('load', () => {
      setTimeout(() => {
        History.blockPopstate = false;
      }, 0);
    });

    if (document.readyState && document.readyState === 'complete') {
      History.blockPopstate = false;
    }

    $(window).on('popstate', History.handle.bind(app));
  },
};

export default History;
