import React from "react";
import ReactDOM from "react-dom";
<%_ if (useStore) { _%>
import { Provider } from "react-redux";
<%_ } _%>
import Loadable from "react-loadable";
import { pathToRegexp } from "path-to-regexp";
import cloneDeepWith from "lodash.clonedeepwith";

import { LubanRouter } from "./router";
import { flattenRoutes } from "./util";

import entry from "../";
import dynamicRoute from "./dynamicRoutes";
import originRoutes from "./originRoutes";
import { BasicRouterItem } from "./definitions";
// @ts-ignore
import { injectPreparerComponentProps } from "./injectPreparerProps";

<%_ if (useStore) { _%>
import { store } from "./store";
<%_ } _%>

<%_ if (isSpecifyPreparer) { _%>
import Preparer from "<%= preparerComponentPath %>";
<%_ } else { _%>
// @ts-ignore
const Preparer = ((props) => <>{props.children}</>);
<%_ } _%>

// @ts-ignore
const Layout = entry.layout || ((props) => <>{props.children}</>);
const root = document.getElementById(entry.root || "root");

const _routes = flattenRoutes(dynamicRoute);

async function preloadComponent(routes: BasicRouterItem[]): Promise<BasicRouterItem[]> {
  const baseName = entry.route.basename;
  const pathName = baseName ? location.pathname.replace(baseName, "") : location.pathname;

  const copyRoutes = cloneDeepWith(routes);

  for (let i in copyRoutes) {
    const { component, path } = copyRoutes[i];
    let activeComponent = component;
    if (activeComponent && activeComponent.preload && pathToRegexp(path).test(pathName)) {
      activeComponent = (await activeComponent.preload()).default;
    }
    copyRoutes[i].component = activeComponent;
  }
  return copyRoutes;
}

function App(props: { routes: BasicRouterItem[] }) {
  let Container = (
    <LubanRouter config={{ ...entry.route, routes: props.routes }} originRouteList={originRoutes}>
      {(props) => {
        return (
          <Layout matchedRouteList={props.matchedRouteList} originRouteList={originRoutes}>
            {props.rendered}
          </Layout>
        );
      }}
    </LubanRouter>
  );

  <%_ if (isSpecifyPreparer) { _%>
  if (Preparer) {
    const Reraperp = injectPreparerComponentProps(Preparer);
    Container = <Reraperp>{Container}</Reraperp>
  }
  <%_ } _%>

  <%_ if (useStore) { _%>
  if (store) {
    // @ts-ignore
    return <Provider store={store}>{Container}</Provider>;
  }
  <%_ } _%>

  return Container;
}

async function clientRender() {
  const loadedRoutes = await preloadComponent(_routes);

  Loadable.preloadReady().then(() => {
    [ReactDOM[window.__USE_SSR__ ? "hydrate" : "render"](<App routes={loadedRoutes} />, root)];
  });
}

clientRender();
