import Route from './entities/Route';
import Router from './entities/Router';

import { error, configure } from './utils/report';

import type {
  Page,
  View,
  Panel,

  Modal,
  Popout,

  RouteList,
  RouteParams,

  RenderNode,
  Structure,

  SharedConfig
} from './types';

let globalRouter: Router | null = null;

export function startGlobalRouter(routes: RouteList, config: Partial<SharedConfig> = {}) {
  configure(config);

  if (globalRouter) {
    error('startGlobalRouter called twice is not allowed');
    return globalRouter;
  }

  globalRouter = new Router(routes);
  return globalRouter;
}

export function getGlobalRouter(): Router {
  if (!globalRouter) {
    error('getGlobalRouter called before startGlobalRouter');
    return;
  }
  return globalRouter;
}

export function pushPage(page: Page, params: RouteParams = {}) {
  return getGlobalRouter().pushPage(page, params);
}

export function replacePage(page: Page, params: RouteParams = {}) {
  return getGlobalRouter().replacePage(page, params);
}

export function popPage() {
  return getGlobalRouter().popPage();
}

export function pushModal(modal: Modal, params: RouteParams = {}) {
  return getGlobalRouter().pushModal(modal, params);
}

export function replaceModal(modal: Modal, params: RouteParams = {}) {
  return getGlobalRouter().replaceModal(modal, params);
}

export function pushPopup(popup: Popout, params: RouteParams = {}) {
  return getGlobalRouter().pushPopup(popup, params);
}

export function replacePopout(popup: Popout, params: RouteParams = {}) {
  return getGlobalRouter().replacePopup(popup, params);
}

export function popPageIfModalOrPopup() {
  return getGlobalRouter().popPageIfModalOrPopup();
}

export function pushPageAfterPreviews(prevPage: Page, nextPage: Page, params: RouteParams = {}) {
  getGlobalRouter().pushPageAfterMove(prevPage, nextPage, params);
}

export function getCurrentRoute() {
  return getGlobalRouter().history.route;
}

export function getLastPanelInView(view: View): Panel {
  return getGlobalRouter().cache.get(view);
}

export function getPanelInView(route: Route, view: View): Panel {
  if (route.view === view) {
    return route.panel;
  } else {
    return getLastPanelInView(view);
  }
}

export function getViewHistory(route: Route, view: View): Structure[] {
  if (route.view === view) {
    return route.history;
  } else {
    const panel = getPanelInView(route, view);
    if (panel) {
      return [panel];
    } else {
      return [];
    }
  }
}

export function getViewProps(view: View, route: Route, modal: RenderNode, popout: RenderNode) {
  return {
    id: view,
    activePanel: getPanelInView(route, view),
    history: route.hasOverlay ? [] : getViewHistory(route, view),
    modal: modal,
    popout: popout,
    params: route.params,
    onSwipeBack: popPage
  };
}

export function getPanelProps(panel: Panel, route: Route) {
  return {
    id: panel,
    params: route.params
  };
}

export function getModalProps(modal: Modal, route: Route) {
  return {
    id: modal,
    params: route.params
  };
}

export function getPopoutProps(popout: Popout, route: Route) {
  return {
    id: popout,
    params: route.params
  };
}
