import { IStoreWithBase } from '../../context/context.interface';
import { startRouter } from '../router';
import { Route, Routing } from './route.interface';

/**
 * Defines the routes of the app and starts the router.
 * @param routes Route[] containing the routes of the app.
 * @param store  IStoreWithBase<S, R> containing the store of the app.
 */
export function defineRoutes<S>(
  routes: Route[],
  store: IStoreWithBase<S>
): IStoreWithBase<S> {
  const { app } = store;
  const { view, popups } = app;

  // set routes
  view.setRoutes(routes);

  const routing: Routing = {};
  routes.forEach((route) => {
    routing[route.path] = (...params) => {
      const path = route.path;

      if (route.beforeOpen) {
        route.beforeOpen(params);
      }
      const routeKeys = parsePathRouteParams(path, params);
      if (params) {
        view.setParams(routeKeys);
      }

      if (route.openPartial) {
        const partialViewId = params[params.length - 1].replace(':', '');
        view.setView(partialViewId, true);
      }
      if (route.popup) {
        // view.setView(route)
        // TODO: handle popup
        popups.set(path, route.title, {});
      }
      view.open(path, route.title, () => {
        /** */
        if (route.onOpen) {
          route.onOpen(params);
        }
      });
    };
  });

  startRouter(store, () => routing);
  return store;
}

function parsePathRouteParams(path: string, params: string[]) {
  const pathParts = path.split('/:');
  const id = pathParts.shift();
  const paramKeys = convertArrayToObject(pathParts, params);

  return {
    path: id,
    ...paramKeys
  };
}

function convertArrayToObject(arr: any[], params: string[]) {
  return arr.reduce((obj, str, i) => {
    obj[str] = params[i];
    return obj;
  }, {});
}
