// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
 * @fileoverview Page navigation utility code.
 */
import { assert, assertNotReached, assertNotReachedCase } from '//resources/js/assert.js';
/**
 * The different pages that can be shown.
 */
export var Page;
(function (Page) {
    Page["LOCAL_CERTS"] = "localcerts";
    Page["CLIENT_CERTS"] = "clientcerts";
    Page["CRS_CERTS"] = "crscerts";
    // Sub-pages
    Page["ADMIN_CERTS"] = "localcerts/admincerts";
    // 
    Page["PLATFORM_CERTS"] = "localcerts/platformcerts";
    // 
    Page["USER_CERTS"] = "localcerts/usercerts";
    Page["PLATFORM_CLIENT_CERTS"] = "clientcerts/platformclientcerts";
})(Page || (Page = {}));
export class Route {
    constructor(page) {
        this.page = page;
    }
    page;
    path() {
        return '/' + this.page;
    }
    isSubpage() {
        switch (this.page) {
            case Page.ADMIN_CERTS:
            // 
            case Page.PLATFORM_CERTS:
            // 
            case Page.PLATFORM_CLIENT_CERTS:
            case Page.USER_CERTS:
                return true;
            case Page.LOCAL_CERTS:
            case Page.CLIENT_CERTS:
            case Page.CRS_CERTS:
                return false;
            default:
                assertNotReachedCase(this.page);
        }
    }
}
/**
 * A helper object to manage in-page navigations.
 */
export class Router {
    static getInstance() {
        return routerInstance || (routerInstance = new Router());
    }
    currentRoute_ = new Route(Page.LOCAL_CERTS);
    previousRoute_ = null;
    routeObservers_ = new Set();
    constructor() {
        this.processRoute_();
        window.addEventListener('popstate', () => {
            this.processRoute_();
        });
    }
    addObserver(observer) {
        assert(!this.routeObservers_.has(observer));
        this.routeObservers_.add(observer);
    }
    removeObserver(observer) {
        assert(this.routeObservers_.delete(observer));
    }
    get currentRoute() {
        return this.currentRoute_;
    }
    get previousRoute() {
        return this.previousRoute_;
    }
    /**
     * Navigates to a page and pushes a new history entry.
     */
    navigateTo(page) {
        const newRoute = new Route(page);
        if (this.currentRoute_.path() === newRoute.path()) {
            return;
        }
        this.recordMetrics(page);
        const oldRoute = this.currentRoute_;
        this.currentRoute_ = newRoute;
        const path = this.currentRoute_.path();
        const state = { url: path };
        history.pushState(state, '', path);
        this.notifyObservers_(oldRoute);
    }
    notifyObservers_(oldRoute) {
        assert(oldRoute !== this.currentRoute_);
        this.previousRoute_ = oldRoute;
        for (const observer of this.routeObservers_) {
            observer.currentRouteChanged(this.currentRoute_, oldRoute);
        }
    }
    static getPageFromPath(path) {
        const page = path.substring(1);
        return Object.values(Page).includes(page) ? page : undefined;
    }
    /**
     * Helper function to set the current page from the path and notify all
     * observers.
     */
    processRoute_() {
        const page = Router.getPageFromPath(location.pathname);
        if (!page) {
            return;
        }
        this.recordMetrics(page);
        const oldRoute = this.currentRoute_;
        this.currentRoute_ = new Route(oldRoute.page);
        this.currentRoute_.page = page;
        this.notifyObservers_(oldRoute);
    }
    // LINT.IfChange(PageHistogramEnum)
    pageToMetricInt(page) {
        // These values are persisted to logs. Entries should not be renumbered and
        // numeric values should never be reused.
        switch (page) {
            case Page.LOCAL_CERTS:
                return 0;
            case Page.CLIENT_CERTS:
                return 1;
            case Page.CRS_CERTS:
                return 2;
            case Page.ADMIN_CERTS:
                return 3;
            case Page.PLATFORM_CLIENT_CERTS:
                return 4;
            // 
            case Page.PLATFORM_CERTS:
                return 5;
            // 
            case Page.USER_CERTS:
                return 6;
            default:
                assertNotReachedCase(page);
        }
    }
    recordMetrics(page) {
        const histogramMaxValue = 6;
        const metricName = 'Net.CertificateManager.PageVisits';
        chrome.metricsPrivate.recordEnumerationValue(metricName, this.pageToMetricInt(page), histogramMaxValue + 1);
    }
}
let routerInstance = null;
export const RouteObserverMixin = (superClass) => {
    class RouteObserverMixin extends superClass {
        connectedCallback() {
            super.connectedCallback();
            Router.getInstance().addObserver(this);
            this.currentRouteChanged(Router.getInstance().currentRoute, Router.getInstance().currentRoute);
        }
        disconnectedCallback() {
            super.disconnectedCallback();
            Router.getInstance().removeObserver(this);
        }
        currentRouteChanged(_newRoute, _oldRoute) {
            assertNotReached();
        }
    }
    return RouteObserverMixin;
};
