import Hostname from "../../Types/API/Hostname";
import Route from "../../Types/API/Route";
import URL from "../../Types/API/URL";
import BadDataException from "../../Types/Exception/BadDataException";
import ObjectID from "../../Types/ObjectID";
import { matchRoutes, } from "react-router-dom";
class Navigation {
    static setNavigateHook(navigateHook) {
        this.navigateHook = navigateHook;
    }
    static setLocation(location) {
        this.location = location;
    }
    static setParams(params) {
        this.params = params;
    }
    static getParams() {
        return this.params;
    }
    static getCurrentPath() {
        return new Route(window.location.pathname);
    }
    static getBreadcrumbRoute(level) {
        const paths = this.location.pathname.split("/");
        // +2 because we want to include the first 2 paths which are empty, dashboard and project id
        const indexToSplice = level + 2;
        return new Route(paths.splice(0, indexToSplice).join("/"));
    }
    static getRoutePath(routes) {
        var _a;
        const pathes = matchRoutes(routes, this.location.pathname);
        return ((_a = pathes === null || pathes === void 0 ? void 0 : pathes[0]) === null || _a === void 0 ? void 0 : _a.route.path) || "";
    }
    static getQueryStringByName(paramName) {
        const urlSearchParams = new URLSearchParams(window.location.search);
        const params = Object.fromEntries(urlSearchParams.entries());
        if (params && params[paramName]) {
            return params[paramName];
        }
        return null;
    }
    /**
     * Update (or remove) query-string params on the current URL *in place*,
     * without pushing a new browser-history entry and without triggering a
     * react-router navigation/re-render. Pass `null` (or "") as a value to
     * delete that param.
     *
     * This is used to keep table filter/facet state in the URL so it survives
     * navigating to a detail page and back, and so a filtered view is
     * shareable/bookmarkable. We use `replaceState` (not push) so changing a
     * filter doesn't flood the back-button history.
     */
    static setQueryString(params) {
        const urlSearchParams = new URLSearchParams(window.location.search);
        for (const paramName in params) {
            const value = params[paramName] === undefined
                ? null
                : params[paramName];
            if (value === null || value === "") {
                urlSearchParams.delete(paramName);
            }
            else {
                urlSearchParams.set(paramName, value);
            }
        }
        const queryString = urlSearchParams.toString();
        const newRelativeUrl = window.location.pathname +
            (queryString ? `?${queryString}` : "") +
            window.location.hash;
        window.history.replaceState(window.history.state, "", newRelativeUrl);
    }
    static getParamByName(paramName, routeTemplate) {
        const currentPath = this.location.pathname.split("/");
        if (!paramName.startsWith(":")) {
            paramName = ":" + paramName;
        }
        const routeParamTemplateIndex = routeTemplate
            .toString()
            .split("/")
            .indexOf(paramName);
        if (routeParamTemplateIndex === -1) {
            throw new BadDataException(`Param ${paramName} not found in template ${routeTemplate.toString()}`);
        }
        if (currentPath[routeParamTemplateIndex]) {
            return currentPath[routeParamTemplateIndex];
        }
        return null;
    }
    static getLastParam(getFromLastRoute) {
        return URL.fromString(window.location.href).getLastRoute(getFromLastRoute);
    }
    static getFirstParam(getFromFirstRoute) {
        const pathname = window.location.pathname;
        return pathname.split("/")[getFromFirstRoute || 1];
    }
    static getLastParamAsString(getFromLastRoute) {
        const param = URL.fromString(window.location.href).getLastRoute(getFromLastRoute);
        return (param === null || param === void 0 ? void 0 : param.toString().replace("/", "")) || "";
    }
    static getLastParamAsObjectID(getFromLastRoute) {
        return new ObjectID(this.getLastParamAsString(getFromLastRoute));
    }
    static getCurrentRoute() {
        return new Route(this.location.pathname);
    }
    static getHostname() {
        return new Hostname(window.location.hostname);
    }
    static getCurrentURL() {
        return URL.fromString(window.location.href);
    }
    static reload() {
        window.location.reload();
    }
    static containsInPath(text) {
        return window.location.pathname.includes(text);
    }
    static isStartWith(route) {
        var _a, _b;
        const current = this.getCurrentRoute();
        const routeItems = route.toString().split("/");
        let anotherRouteItems = current.toString().split("/");
        if (routeItems.length > anotherRouteItems.length) {
            return false;
        }
        anotherRouteItems = anotherRouteItems.splice(0, routeItems.length);
        let start = 0;
        let startsWith = true;
        for (const item of anotherRouteItems) {
            if (((_a = routeItems[start]) === null || _a === void 0 ? void 0 : _a.startsWith(":")) && item) {
                start++;
                continue;
            }
            if (((_b = routeItems[start]) === null || _b === void 0 ? void 0 : _b.toString()) !== item.toString()) {
                startsWith = false;
                break;
            }
            start++;
        }
        return startsWith;
    }
    static isOnThisPage(route) {
        var _a, _b;
        if (route instanceof Route) {
            const current = this.getCurrentRoute();
            let isOnThisPage = true;
            const routeItems = route.toString().split("/");
            const currentPathItems = current.toString().split("/");
            if (routeItems.length !== currentPathItems.length) {
                return false;
            }
            let start = 0;
            for (const item of currentPathItems) {
                if (((_a = routeItems[start]) === null || _a === void 0 ? void 0 : _a.startsWith(":")) && item) {
                    start++;
                    continue;
                }
                if (((_b = routeItems[start]) === null || _b === void 0 ? void 0 : _b.toString()) !== item.toString()) {
                    isOnThisPage = false;
                    break;
                }
                start++;
            }
            return isOnThisPage;
        }
        if (route instanceof URL) {
            const current = this.getCurrentURL();
            if (current.toString() === route.toString()) {
                return true;
            }
            return false;
        }
        return false;
    }
    static goBack() {
        this.navigateHook(-1);
    }
    static navigate(to, options) {
        const finalUrl = to.toString();
        // add query params if they exist.
        if (options === null || options === void 0 ? void 0 : options.openInNewTab) {
            // open in new tab
            window.open(finalUrl, "_blank");
            return;
        }
        if ((options === null || options === void 0 ? void 0 : options.forceNavigate) && to instanceof Route) {
            window.location.href = finalUrl;
            return;
        }
        if (this.navigateHook && to instanceof Route && !this.isOnThisPage(to)) {
            this.navigateHook(finalUrl);
        }
        // if its an external link outside of react.
        if (to instanceof URL) {
            window.location.href = finalUrl;
        }
    }
}
export default Navigation;
//# sourceMappingURL=Navigation.js.map