// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import { BrowserBridge } from './browser_bridge.js';
// 
import { DnsView } from './dns_view.js';
import { DomainSecurityPolicyView } from './domain_security_policy_view.js';
import { EventsView } from './events_view.js';
import { ProxyView } from './proxy_view.js';
import { SharedDictionaryView } from './shared_dictionary_view.js';
import { SocketsView } from './sockets_view.js';
import { TabSwitcherView } from './tab_switcher_view.js';
import { hasTouchScreen } from './util.js';
import { UtilitiesView } from './utilities_view.js';
import { WindowView } from './view.js';
/** @type {?MainView} */
let instance = null;
/**
 * This class is the root view object of the page.  It owns all the other
 * views, and manages switching between them.  It is also responsible for
 * initializing the views and the BrowserBridge.
 */
export class MainView extends WindowView {
    constructor() {
        if (hasTouchScreen()) {
            document.body.classList.add('touch');
        }
        const tabSwitcher = new TabSwitcherView();
        super(tabSwitcher);
        this.tabSwitcher_ = tabSwitcher;
        // Create the tab switcher.
        this.initTabs_();
        // Trigger initial layout.
        this.resetGeometry();
        window.onhashchange = this.onUrlHashChange_.bind(this);
        // Select the initial view based on the current URL.
        window.onhashchange();
    }
    // This is exposed for testing.
    tabSwitcher() {
        return this.tabSwitcher_;
    }
    initTabs_() {
        this.tabIdToHash_ = {};
        this.hashToTabId_ = {};
        this.tabSwitcher_.setOnTabSwitched(this.onTabSwitched_.bind(this));
        // Helper function to add a tab given the class for a view singleton.
        const addTab = function (viewClass) {
            const tabId = viewClass.TAB_ID;
            const tabHash = viewClass.TAB_HASH;
            const tabName = viewClass.TAB_NAME;
            const view = viewClass.getInstance();
            if (!tabId || !view || !tabHash || !tabName) {
                throw Error('Invalid view class for tab');
            }
            if (tabHash.charAt(0) !== '#') {
                throw Error('Tab hashes must start with a #');
            }
            this.tabSwitcher_.addTab(tabId, view, tabName, tabHash);
            this.tabIdToHash_[tabId] = tabHash;
            this.hashToTabId_[tabHash] = tabId;
        }.bind(this);
        // Populate the main tabs.
        addTab(EventsView);
        addTab(ProxyView);
        addTab(DnsView);
        addTab(SocketsView);
        addTab(DomainSecurityPolicyView);
        addTab(SharedDictionaryView);
        addTab(UtilitiesView);
        // 
    }
    /**
     * This function is called by the tab switcher when the current tab has been
     * changed. It will update the current URL to reflect the new active tab,
     * so the back can be used to return to previous view.
     */
    onTabSwitched_(oldTabId, newTabId) {
        // Change the URL to match the new tab.
        const newTabHash = this.tabIdToHash_[newTabId];
        const parsed = parseUrlHash_(window.location.hash);
        if (parsed.tabHash !== newTabHash) {
            window.location.hash = newTabHash;
        }
    }
    onUrlHashChange_() {
        const parsed = parseUrlHash_(window.location.hash);
        if (!parsed) {
            return;
        }
        // Redirect deleted pages to #events page, which contains instructions
        // about migrating to using net-export and the external netlog_viewer.
        if ([
            '#capture',
            '#import',
            '#export',
            '#timeline',
            '#alt-svc',
            '#http2',
            '#quic',
            '#reporting',
            '#httpCache',
            '#modules',
            '#bandwidth',
            '#prerender',
        ].includes(parsed.tabHash)) {
            parsed.tabHash = EventsView.TAB_HASH;
        }
        // 
        // Don't switch to the chromeos view if not on chromeos.
        if (parsed.tabHash === '#chromeos') {
            parsed.tabHash = EventsView.TAB_HASH;
        }
        // 
        if (!parsed.tabHash) {
            // Default to the events tab.
            parsed.tabHash = EventsView.TAB_HASH;
        }
        const tabId = this.hashToTabId_[parsed.tabHash];
        if (tabId) {
            this.tabSwitcher_.switchToTab(tabId);
            if (parsed.parameters) {
                const view = this.tabSwitcher_.getTabView(tabId);
                view.setParameters(parsed.parameters);
            }
        }
    }
    static getInstance() {
        return instance || (instance = new MainView());
    }
}
/**
 * Takes the current hash in form of "#tab&param1=value1&param2=value2&..."
 * and parses it into a dictionary.
 *
 * Parameters and values are decoded with decodeURIComponent().
 */
function parseUrlHash_(hash) {
    const parameters = hash.split('&');
    let tabHash = parameters[0];
    if (tabHash === '' || tabHash === '#') {
        tabHash = undefined;
    }
    // Split each string except the first around the '='.
    let paramDict = null;
    for (let i = 1; i < parameters.length; i++) {
        const paramStrings = parameters[i].split('=');
        if (paramStrings.length !== 2) {
            continue;
        }
        if (paramDict == null) {
            paramDict = {};
        }
        const key = decodeURIComponent(paramStrings[0]);
        const value = decodeURIComponent(paramStrings[1]);
        paramDict[key] = value;
    }
    return { tabHash: tabHash, parameters: paramDict };
}
