import utils from 'somes';
import * as React from 'react';
import { Component } from 'react';
import { Router as RouterRaw, Route as RouteRaw, Switch } from 'react-router-dom';
import handles from './errno_handles';
import somes from 'somes';
import Page, { Loading } from './page';
import NotFound from './404';
import * as _history from 'history';
export const history = _history.createBrowserHistory();
function route(router, { path, page, ...args }) {
    class _Route extends Component {
        constructor() {
            super(...arguments);
            this.state = { com: Loading, isLoaded: false };
        }
        async componentDidMount() {
            if (!this.state.isLoaded) {
                try {
                    var com = (await page()).default;
                    somes.assert(somes.equalsClass(Page, com), 'Page TypeError, somes.equalsClass(Page, com)');
                    this.setState({ com, isLoaded: true });
                }
                catch (err) {
                    handles(err);
                }
            }
        }
        render() {
            var Com = this.state.com;
            return (React.createElement(Com, { router: router, history: history, location: this.props.location, match: this.props.match }));
        }
    }
    return React.createElement(RouteRaw, Object.assign({ path: path, key: path }, args, { component: _Route }));
}
export class Router extends Component {
    constructor(props) {
        super(props);
        this._routes = {};
        this._current = null;
        (this.props.routes || []).forEach(e => {
            if (e.path) {
                if (Array.isArray(e.path)) {
                    e.path.forEach(j => {
                        this._routes[j] = { ...e, path: j };
                    });
                }
                else {
                    this._routes[e.path] = e;
                }
            }
        });
        this._notFound = this.props.notFound || NotFound;
    }
    get current() {
        utils.assert(this._current);
        return this._current;
    }
    get history() {
        return history;
    }
    render() {
        var notFound = { path: '', page: async () => ({ default: this._notFound }) };
        return (React.createElement(RouterRaw, { history: this.history },
            React.createElement(Switch, null,
                Object.values(this._routes).map(e => route(this, e)),
                route(this, notFound))));
    }
}
