import page from "page";
export class Router {
    constructor() {
        this._url = '/';
        this.routes = [];
        this.hash = '';
    }
    componentDidLoad() {
        this.el.style.display = "none";
        this.postRender();
        if (this.level == 0) {
            page(window.location.pathname);
        }
    }
    componentDidUpdate() {
        this.postRender();
    }
    postRender() {
        let routeComponents = Array.from(this.el.getElementsByTagName('ema-route'));
        routeComponents.forEach((route) => {
            this.routes.push({
                'component': route.component,
                'component-props': route.componentProps,
                'url': route.url,
                'exact': route.exact,
                'action': route.action,
                'action-params': route.actionParams,
            });
        });
        this.routes.forEach((route) => {
            page(route.url, (pageContext) => {
                if (route.component) {
                    pageContext.state.component = route.component;
                }
                this._pageContext = pageContext;
                this.state = {
                    context: pageContext,
                    route: route,
                    routes: this.routes,
                    component: route.component,
                };
                this.activateRoute();
                this.change.emit(this.state);
            });
        });
    }
    activateRoute() {
        let breadcrumb = [];
        let component;
        let currentPathRoot;
        let pageClass = 'page';
        let pageContext = this.state.context;
        let params = pageContext.params;
        let route = this.state.route;
        let routeComponent;
        let url = this._url = pageContext.state.path;
        let urlParsed = this.urlParamsToUrl(route.url);
        if (!route.component) {
            console.error('No component defined for url: ' + url);
            return;
        }
        else {
            component = route.component;
        }
        this.deleteRouterClasses();
        pageContext.state.path.split('/').forEach((p) => {
            if (p !== '') {
                breadcrumb.push(p);
            }
        });
        if (pageContext.state.component) {
            routeComponent = pageContext.state.component;
        }
        breadcrumb.forEach((level) => {
            pageClass += ('-' + level);
            this.removeClass(document.querySelector('body'), pageClass);
        });
        if (breadcrumb.length) {
            currentPathRoot = breadcrumb[0];
        }
        if (component && component === routeComponent && url === urlParsed) {
            if (route['exact'] && route['url'] !== url) {
            }
            if (this._compDiv) {
                if (this.targetSelector) {
                    if (document.querySelector(this.targetSelector)) {
                        document.querySelector(this.targetSelector).removeChild(this._compDiv);
                    }
                }
                else {
                    this.el.parentNode.removeChild(this._compDiv);
                }
            }
            this._compDiv = document.createElement(component);
            if (route['component-props']) {
                let cprops = JSON.parse(route['component-props']);
                Object.keys(cprops).forEach((k) => {
                    let v = cprops[k];
                    if (typeof v !== 'string') {
                        v = JSON.stringify(v);
                    }
                    this._compDiv.setAttribute(k, v);
                });
            }
            if (this.targetSelector) {
                if (document.querySelector(this.targetSelector)) {
                    document.querySelector(this.targetSelector).appendChild(this._compDiv);
                }
            }
            else {
                this.el.parentNode.insertBefore(this._compDiv, this.el.nextSibling);
            }
            this.addClass(document.querySelector('body'), component);
        }
        this.addClass(document.querySelector('body'), pageClass);
    }
    deleteRouterClasses() {
        let bodyElement = document.querySelector('body');
        this.state.routes.forEach((r) => {
            if (r.component) {
                this.removeClass(bodyElement, r.component);
            }
        });
        bodyElement.classList.forEach((classId) => {
            if (classId.startsWith('page-')) {
                this.removeClass(bodyElement, classId);
            }
        });
    }
    urlParamsToUrl(url) {
        let parsedUrl = url;
        let params = this.state.context.params;
        let parts = url.split('/');
        let hasParams = false;
        parts.forEach((part, i) => {
            let variable;
            let value;
            if (part.startsWith(':')) {
                hasParams = true;
                variable = part.split(':')[1];
                value = params[variable];
                parsedUrl = parsedUrl.replace(part, value);
            }
        });
        if (hasParams) {
            return parsedUrl;
        }
        else {
            return url;
        }
    }
    async url(url) {
        if (url) {
            page(this.hash + url);
        }
        else {
            return this._url;
        }
    }
    async page() {
        return page;
    }
    async getState() {
        return this.state;
    }
    addClass(el, className) {
        if (el.classList)
            el.classList.add(className);
        else
            el.className += ' ' + className;
    }
    removeClass(el, className) {
        if (el.classList)
            el.classList.remove(className);
        else
            el.className = el.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
    }
    render() {
        return (h("div", null));
    }
    static get is() { return "ema-router"; }
    static get properties() { return {
        "dataJson": {
            "type": String,
            "attr": "data-json"
        },
        "el": {
            "elementRef": true
        },
        "getState": {
            "method": true
        },
        "hash": {
            "type": String,
            "attr": "hash"
        },
        "level": {
            "type": Number,
            "attr": "level"
        },
        "page": {
            "method": true
        },
        "routerLinks": {
            "state": true
        },
        "routes": {
            "state": true
        },
        "state": {
            "state": true
        },
        "targetSelector": {
            "type": String,
            "attr": "target-selector"
        },
        "url": {
            "method": true
        }
    }; }
    static get events() { return [{
            "name": "change",
            "method": "change",
            "bubbles": true,
            "cancelable": true,
            "composed": true
        }]; }
}
