// @babel ignore
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments)).next());
    });
};
const React = require('react');
const server_1 = require('react-dom/server');
const react_router_1 = require('react-router');
const react_redux_1 = require('react-redux');
const server_request_1 = require('../server-request');
const fetch_1 = require('../fetch');
const store_1 = require('../store');
const service_1 = require('../service');
// 渲染整个页面
const renderFullPage = (htmlText, element, initialState, initialTitle) => {
    let content = htmlText;
    // 将内容塞到 #react-dom
    content = content.replace(/<div id=\"react-dom\"><\/div>/g, `<div id="react-dom">${element}</div>`);
    // 设置 Redux 初始状态
    content = content.replace(/__serverData\((\'|\")__INITIAL_STATE__(\'|\")\)/g, JSON.stringify(initialState));
    // 设置 title
    content = content.replace(/__serverData\((\'|\")__INITIAL_TITLE__(\'|\")\)/g, initialTitle);
    return content;
};
/**
 * 后端渲染 promise
 */
const getMatch = (option) => {
    return new Promise((resolve, reject) => {
        react_router_1.match({
            routes: option.routes,
            location: option.req.url,
            basename: option.basename
        }, (error, redirectLocation, renderProps) => {
            if (error) {
                resolve({
                    status: 500,
                    result: error.message
                });
            }
            else if (redirectLocation) {
                resolve({
                    status: 302,
                    result: redirectLocation.pathname + redirectLocation.search
                });
            }
            else if (renderProps) {
                const serverRequestHelper = new server_request_1.default(service_1.default, option.req);
                // 初始化 fetch
                fetch_1.setServerRender(serverRequestHelper.Request);
                // 初始化 redux
                const store = store_1.default({}, option.rootReducer);
                const InitialView = React.createElement(react_redux_1.Provider, { store: store }, React.createElement(react_router_1.RouterContext, renderProps));
                // 找到最深层组件的 title
                const title = renderProps.components[renderProps.components.length - 1].title;
                try {
                    // 初次渲染触发所有需要的网络请求
                    server_1.renderToString(InitialView);
                    // 拿到这些请求的action
                    const actions = serverRequestHelper.getActions();
                    Promise.all(actions.map((action) => {
                        return store.dispatch(action);
                    })).then(() => {
                        const componentHTML = server_1.renderToString(InitialView);
                        const initialState = store.getState();
                        // 将初始状态输出到 html
                        resolve({
                            status: 200,
                            result: renderFullPage(option.htmlText, componentHTML, initialState, title)
                        });
                    });
                }
                catch (err) {
                    resolve({
                        status: 200,
                        result: renderFullPage(option.htmlText, `Server Render Error: ${err.toString()}`, {}, title)
                    });
                }
            }
            else {
                resolve({
                    status: 404,
                    result: 'Not Found'
                });
            }
        });
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = (option) => __awaiter(this, void 0, void 0, function* () {
    // 如果不启动后端渲染,直接返回未加工的模板
    if (!option.enableServerRender) {
        return {
            status: 200,
            result: renderFullPage(option.htmlText, '', {}, '')
        };
    }
    return yield getMatch(option);
});
