const WORD_REGEX = /^[^//][^.]*$/;
const VALID_URI_REGEX = /^[-:.&#+()[\]$'*;@~!,?%=\/\w]+$/; // Will check that only RFC3986 allowed characters are included
const SCHEMED_URI_REGEX = /^\w+:.+$/;

let settings = {
    scriptsEnabled: true,
    blockPopups: true,
    disableCtrlEnter: false,
    disableFavorites: false,
    disableSettings: false,
    disableHistory: false,
    hideFavoritesButton: false,
    disableLastTabCloseWindow: false
};

const messageHandler = event => {
    var message = event.data.message;
    var args = event.data.args;

    switch (message) {
        case commands.MG_UPDATE_URI:
            if (isValidTabId(args.tabId)) {
                const tab = tabs.get(args.tabId);
                let previousURI = tab.uri;

                // Update the tab state
                tab.uri = args.uri;
                tab.uriToShow = args.uriToShow;
                tab.canGoBack = args.canGoBack;
                tab.canGoForward = args.canGoForward;

                // If the tab is active, update the controls UI
                if (args.tabId == activeTabId) {
                    updateNavigationUI(message);
                }

                isFavorite(tab.uri, (isFavorite) => {
                    tab.isFavorite = isFavorite;
                    updateFavoriteIcon();
                });

                // Don't add history entry if URI has not changed
                if (tab.uri == previousURI) {
                    break;
                }

                // Filter URIs that should not appear in history
                if (!tab.uri || tab.uri == 'about:blank') {
                    tab.historyItemId = INVALID_HISTORY_ID;
                    break;
                }

                if (tab.uriToShow && tab.uriToShow.substring(0, 10) == 'browser://') {
                    tab.historyItemId = INVALID_HISTORY_ID;
                    break;
                }

                addHistoryItem(historyItemFromTab(args.tabId), (id) => {
                    tab.historyItemId = id;
                });
            }
            break;
        case commands.MG_NAV_STARTING:
            if (isValidTabId(args.tabId)) {
                // Update the tab state
                tabs.get(args.tabId).isLoading = true;

                // If the tab is active, update the controls UI
                if (args.tabId == activeTabId) {
                    updateNavigationUI(message);
                }
            }
            break;
        case commands.MG_NAV_COMPLETED:
            if (isValidTabId(args.tabId)) {
                // Update tab state
                tabs.get(args.tabId).isLoading = false;

                // If the tab is active, update the controls UI
                if (args.tabId == activeTabId) {
                    updateNavigationUI(message);
                }
            }
            break;
        case commands.MG_UPDATE_TAB:
            if (isValidTabId(args.tabId)) {
                const tab = tabs.get(args.tabId);
                const tabElement = document.getElementById(`tab-${args.tabId}`);

                if (!tabElement) {
                    refreshTabs();
                    return;
                }

                // Update tab label
                // Use given title or fall back to a generic tab title
                tab.title = args.title || 'Tab';
                const tabLabelSpan = tabElement.querySelector('.tab-label span');
                if (tabLabelSpan) {
                    tabLabelSpan.textContent = tab.title;
                }

                // Update title in history item
                // Browser pages will keep an invalid history ID
                if (tab.historyItemId != INVALID_HISTORY_ID) {
                    updateHistoryItem(tab.historyItemId, historyItemFromTab(args.tabId));
                }
            }
            break;
        case commands.MG_OPTIONS_LOST_FOCUS:
            let optionsButton = document.getElementById('btn-options');
            if (optionsButton) {
                if (optionsButton.className = 'btn-active') {
                    toggleOptionsDropdown();
                }
            }
            break;
        case commands.MG_SECURITY_UPDATE:
            if (isValidTabId(args.tabId)) {
                const tab = tabs.get(args.tabId);
                tab.securityState = args.state;

                if (args.tabId == activeTabId) {
                    updateNavigationUI(message);
                }
            }
            break;
        case commands.MG_UPDATE_FAVICON:
            if (isValidTabId(args.tabId)) {
                updateFaviconURI(args.tabId, args.uri);
            }
            break;
        case commands.MG_CLOSE_WINDOW:
            closeWindow();
            break;
        case commands.MG_OPEN_NEW_TAB:
            createNewTab(true);
            break;
        case commands.MG_TRIGGER_FAVORITE:
            toggleFavorite();
            break;
        case commands.MG_REQUEST_CLOSE_TAB:
            closeTab(args.tabId);
            break;
        case commands.MG_BUTTON_VISIBILITY:
            setButtonVisibility(args);
            break;
        case commands.MG_WINDOW_STATE:
            setMaximizeButtonState(args.maximized);
            break;
        case commands.MG_UPDATE_TIMER:
            updateTimerField(args.time);
            break;
        case commands.MG_UPDATE_ACTIVITY:
            updateActivityField(args.time);
            break;
        case commands.MG_UPDATE_ZOOM:
            updateZoomField(args.zoom);
            break;
        case commands.MG_LOAD_FILE_FAVORITES:
            if (args.clearExisting) {
                clearFavorites(() => {
                    importFileFavorites(args.favorites);
                });
            } else {
                importFileFavorites(args.favorites);
            }
            break;
        case commands.MG_GET_FAVORITES:
            if (isValidTabId(args.tabId)) {
                getFavoritesAsJson((payload) => {
                    args.favorites = payload;
                    args.hideFavoritesButton = settings.hideFavoritesButton;
                    window.chrome.webview.postMessage(event.data);
                });
            }
            break;
        case commands.MG_REMOVE_FAVORITE:
            removeFavorite(args.uri);
            break;
        case commands.MG_CLEAR_FAVORITES:
            clearFavorites(() => {
                if (isValidTabId(args.tabId)) {
                    args.cleared = true;
                    window.chrome.webview.postMessage(event.data);
                }
            });
            break;
        case commands.MG_REORDER_FAVORITES:
            reorderFavorites(args.uris);
            break;
        case commands.MG_GET_SETTINGS:
            if (isValidTabId(args.tabId)) {
                args.settings = settings;
                window.chrome.webview.postMessage(event.data);
            }
            break;
        case commands.MG_GET_HISTORY:
            if (isValidTabId(args.tabId)) {
                getHistoryItems(args.from, args.count, (payload) => {
                    args.items = payload;
                    window.chrome.webview.postMessage(event.data);
                });
            }
            break;
        case commands.MG_REMOVE_HISTORY_ITEM:
            removeHistoryItem(args.id);
            break;
        case commands.MG_CLEAR_HISTORY:
            clearHistory();
            break;
        default:
            console.log(`Received unexpected message: ${JSON.stringify(event.data)}`);
    }
};

function processAddressBarInput() {
    var text = document.querySelector('#address-field').value;
    tryNavigate(text);
}

function processAddressBarInputValue(text) {
    tryNavigate(text);
}

function tryNavigate(text) {
    if (settings.overrideURLKeyword && text === settings.overrideURLKeyword) {
        const el = document.getElementById('address-field');
        if (el) el.value = '';
        window.chrome.webview.postMessage({ message: commands.MG_OVERRIDES, args: {} });
        return;
    }
    try {
        var uriParser = new URL(text);
        navigateActiveTab(uriParser.href, false);
    } catch (e) {
        // URL creation failed, check for invalid characters
        if (containsIlegalCharacters(text) || isSingleWord(text)) {
            // Search Bing
            navigateActiveTab(getSearchURI(text), true);
        } else {
            // Try with HTTP
            if (!hasScheme(text)) {
                tryNavigate(`http:${text}`);
            } else {
                navigateActiveTab(getSearchURI(text), true);
            }
        }
    }
}

function navigateActiveTab(uri, isSearch) {
    var message = {
        message: commands.MG_NAVIGATE,
        args: {
            uri: uri,
            encodedSearchURI: isSearch ? uri : getSearchURI(uri)
        }
    };

    window.chrome.webview.postMessage(message);
}

function reloadActiveTabContent() {
    var message = {
        message: commands.MG_RELOAD,
        args: {}
    };
    window.chrome.webview.postMessage(message);
}

function containsIlegalCharacters(query) {
    return !VALID_URI_REGEX.test(query);
}

function isSingleWord(query) {
    return WORD_REGEX.test(query);
}

function hasScheme(query) {
    return SCHEMED_URI_REGEX.test(query);
}

function getSearchURI(query) {
    return `https://google.com/search?q=${encodeURIComponent(query)}`;
}

function closeWindow() {
    clearFavorites(() => {
        var message = {
            message: commands.MG_CLOSE_WINDOW,
            args: {}
        };
        window.chrome.webview.postMessage(message);
    });
}

// Show active tab's URI in the address bar
function updateURI() {
    if (activeTabId == INVALID_TAB_ID) {
        return;
    }

    let activeTab = tabs.get(activeTabId);
    document.getElementById('address-field').value = activeTab.uriToShow || activeTab.uri;
}

// Show active tab's favicon in the tab strip
function updateFavicon() {
    if (activeTabId == INVALID_TAB_ID) {
        return;
    }

    let activeTab = tabs.get(activeTabId);

    let tabElement = document.getElementById(`tab-${activeTabId}`);
    if (!tabElement) {
        return;
    }

    let faviconDiv = tabElement.querySelector('.tab-favicon');
    if (faviconDiv) {
        faviconDiv.style.backgroundImage = `url(${activeTab.favicon})`;
    }
}

function updateTabLoadingSpinner() {
    if (activeTabId == INVALID_TAB_ID) {
        return;
    }

    let activeTab = tabs.get(activeTabId);
    let tabElement = document.getElementById(`tab-${activeTabId}`);
    if (!tabElement) {
        return;
    }

    let faviconDiv = tabElement.querySelector('.tab-favicon');
    if (faviconDiv) {
        if (activeTab.isLoading) {
            faviconDiv.classList.add('loading');
        } else {
            faviconDiv.classList.remove('loading');
        }
    }
}

// Update back and forward buttons for the active tab
function updateBackForwardButtons() {
    if (activeTabId == INVALID_TAB_ID) {
        return;
    }

    let activeTab = tabs.get(activeTabId);
    let btnForward = document.getElementById('btn-forward');
    let btnBack = document.getElementById('btn-back');

    if (!btnBack || !btnForward) {
        refreshControls();
        return;
    }

    if (activeTab.canGoForward)
        btnForward.className = 'btn';
    else
        btnForward.className = 'btn-disabled';

    if (activeTab.canGoBack)
        btnBack.className = 'btn';
    else
        btnBack.className = 'btn-disabled';
}

// Update reload button for the active tab
function updateReloadButton() {
    if (activeTabId == INVALID_TAB_ID) {
        return;
    }

    let activeTab = tabs.get(activeTabId);

    let btnReload = document.getElementById('btn-reload');
    if (!btnReload) {
        refreshControls();
        return;
    }

    btnReload.className = activeTab.isLoading ? 'btn-cancel' : 'btn';
}

// Update lock icon for the active tab
function updateLockIcon() {
    if (activeTabId == INVALID_TAB_ID) {
        return;
    }

    let activeTab = tabs.get(activeTabId);
    let labelElement = document.getElementById('security-label');
    if (!labelElement) {
        refreshControls();
        return;
    }

    switch (activeTab.securityState) {
        case 'insecure':
            labelElement.className = 'label-insecure';
            break;
        case 'neutral':
            labelElement.className = 'label-neutral';
            break;
        case 'secure':
            labelElement.className = 'label-secure';
            break;
        default:
            labelElement.className = 'label-unknown';
            break;
    }
}

// Update favorite status for the active tab
function updateFavoriteIcon() {
    if (activeTabId == INVALID_TAB_ID) {
        return;
    }

    let activeTab = tabs.get(activeTabId);
    isFavorite(activeTab.uri, (isFavorite) => {
        let favoriteElement = document.getElementById('btn-fav');
        if (!favoriteElement) {
            refreshControls();
            return;
        }

        if (isFavorite) {
            favoriteElement.classList.add('favorited');
            activeTab.isFavorite = true;
        } else {
            favoriteElement.classList.remove('favorited');
            activeTab.isFavorite = false;
        }
    });

}

function updateNavigationUI(reason) {
    switch (reason) {
        case commands.MG_UPDATE_URI:
            updateURI();
            updateFavoriteIcon();
            updateBackForwardButtons();
            break;
        case commands.MG_NAV_COMPLETED:
        case commands.MG_NAV_STARTING:
            updateReloadButton();
            updateTabLoadingSpinner();
            break;
        case commands.MG_SECURITY_UPDATE:
            updateLockIcon();
            break;
        case commands.MG_UPDATE_FAVICON:
            updateFavicon();
            break;
        // If a reason is not provided (for requests not originating from a
        // message), default to switch tab behavior.
        default:
        case commands.MG_SWITCH_TAB:
            updateURI();
            updateLockIcon();
            updateFavicon();
            updateFavoriteIcon();
            updateReloadButton();
            updateBackForwardButtons();
            updateTabLoadingSpinner();
            break;
    }
}

function loadTabUI(tabId) {
    if (isValidTabId(tabId)) {
        let tab = tabs.get(tabId);

        let tabElement = document.createElement('div');
        tabElement.className = tabId == activeTabId ? 'tab-active' : 'tab';
        tabElement.id = `tab-${tabId}`;

        let tabFavicon = document.createElement('div');
        tabFavicon.className = 'tab-favicon';
        tabFavicon.style.backgroundImage = `url(${tab.favicon})`;
        if (tab.isLoading) tabFavicon.classList.add('loading');
        tabElement.appendChild(tabFavicon);

        let tabLabel = document.createElement('div');
        tabLabel.className = 'tab-label';

        let labelText = document.createElement('span');
        labelText.textContent = tab.title;
        tabLabel.appendChild(labelText);

        let closeButton = document.createElement('div');
        closeButton.className = 'btn-tab-close';
        closeButton.addEventListener('click', function(e) {
            closeTab(tabId);
        });

        tabElement.appendChild(tabLabel);
        tabElement.appendChild(closeButton);

        var createTabButton = document.getElementById('btn-new-tab');
        document.getElementById('tabs-strip').insertBefore(tabElement, createTabButton);

        tabElement.addEventListener('click', function(e) {
            if (e.srcElement.className != 'btn-tab-close') {
                switchToTab(tabId, true);
            }
        });

        updateCloseButtonVisibility();
    }
}

function toggleOptionsDropdown() {
    const optionsButtonElement = document.getElementById('btn-options');
    const elementClass = optionsButtonElement.className;

    var message;
    if (elementClass === 'btn') {
        // Update UI
        optionsButtonElement.className = 'btn-active';

        message = {
            message: commands.MG_SHOW_OPTIONS,
            args: {}
        };
    } else {
        // Update UI
        optionsButtonElement.className = 'btn';

        message = {
            message:commands.MG_HIDE_OPTIONS,
            args: {}
        };
    }

    window.chrome.webview.postMessage(message);
}

function setMaximizeButtonState(maximized) {
    const el = document.getElementById('btn-window-maximize');
    if (!el) return;
    if (maximized) {
        el.innerHTML = '<svg viewBox="0 0 10 10"><path d="M1 3 V1 H7 V3 M3 3 H9 V9 H3 Z" fill="none" stroke-width="1"/></svg>';
    } else {
        el.innerHTML = '<svg viewBox="0 0 10 10"><rect x="1" y="1" width="8" height="8" fill="none" stroke-width="1"/></svg>';
    }
}

function setButtonVisibility(args) {
    const buttonMap = {
        back: 'btn-back',
        forward: 'btn-forward',
        reload: 'btn-reload',
        home: 'btn-home',
        favorites: 'btn-favorites',
        print: 'btn-print',
        newWindow: 'btn-new-window'
    };
    for (const [key, id] of Object.entries(buttonMap)) {
        const el = document.getElementById(id);
        if (el) {
            el.style.display = args[key] ? '' : 'none';
        }
    }

    if (args.disableMinimize) {
        const el = document.getElementById('btn-window-minimize');
        if (el) el.style.display = 'none';
    }
    if (args.disableMaximize) {
        const el = document.getElementById('btn-window-maximize');
        if (el) el.style.display = 'none';
    }
    if (args.maximized !== undefined) {
        setMaximizeButtonState(args.maximized);
    }
    if (args.disableClose) {
        const el = document.getElementById('btn-window-close');
        if (el) el.style.display = 'none';
    }
    if (args.disableNewTab) {
        const el = document.getElementById('btn-new-tab');
        if (el) el.style.display = 'none';
    }
    if (args.disableNewWindow) {
        const el = document.getElementById('btn-new-window');
        if (el) el.style.display = 'none';
    }
    if (args.addressBarReadOnly) {
        const el = document.getElementById('address-field');
        if (el) el.readOnly = true;
    }
    if (args.disableCtrlEnter !== undefined) {
        settings.disableCtrlEnter = args.disableCtrlEnter;
    }
    if (args.hideFavoritesButton !== undefined) {
        settings.hideFavoritesButton = args.hideFavoritesButton;
        const el = document.getElementById('btn-fav');
        if (el) el.style.display = args.hideFavoritesButton ? 'none' : '';
    }
    if (args.disableFavorites !== undefined) {
        settings.disableFavorites = args.disableFavorites;
    }
    if (args.disableSettings !== undefined) {
        settings.disableSettings = args.disableSettings;
    }
    if (args.disableHistory !== undefined) {
        settings.disableHistory = args.disableHistory;
    }
    if (settings.disableFavorites && settings.disableSettings && settings.disableHistory) {
        const el = document.getElementById('btn-options');
        if (el) el.style.display = 'none';
    }
    if (args.disableLastTabCloseWindow !== undefined) {
        settings.disableLastTabCloseWindow = args.disableLastTabCloseWindow;
        updateCloseButtonVisibility();
    }
    if (args.hideSettingsButton !== undefined) {
        if (args.hideSettingsButton) {
            const el = document.getElementById('manage-controls-container');
            if (el) el.style.display = 'none';
        }
    }
    if (args.showAddressBar !== undefined && !args.showAddressBar) {
        const el = document.getElementById('address-bar-container');
        if (el) el.style.display = 'none';
    }
    if (args.showNavigationBar !== undefined && !args.showNavigationBar) {
        const el = document.getElementById('controls-bar');
        if (el) el.style.display = 'none';
        document.documentElement.style.height = '32px';
        document.body.style.height = '32px';
    }
    if (args.showInactivityTimer !== undefined) {
        const el = document.getElementById('inactivity-timer-field');
        if (el) {
            if (args.showInactivityTimer) {
                el.style.display = '';
                if (args.inactivityTime !== undefined) {
                    el.textContent = args.inactivityTime;
                }
            } else {
                el.style.display = 'none';
            }
        }
    }
    if (args.showActivityTimer !== undefined) {
        const el = document.getElementById('activity-timer-field');
        if (el) {
            if (args.showActivityTimer) {
                el.style.display = '';
                if (args.activityTime !== undefined) {
                    el.textContent = args.activityTime;
                }
            } else {
                el.style.display = 'none';
            }
        }
    }
    if (args.overrideURLKeyword !== undefined) {
        settings.overrideURLKeyword = args.overrideURLKeyword;
    }
}

function updateTimerField(timeStr) {
    const el = document.getElementById('inactivity-timer-field');
    if (el) el.textContent = timeStr;
}

function updateActivityField(timeStr) {
    const el = document.getElementById('activity-timer-field');
    if (el) el.textContent = timeStr;
}

function updateZoomField(zoomStr) {
    const el = document.getElementById('zoom-field');
    if (el) {
        el.textContent = zoomStr;
        el.style.display = zoomStr === '100%' ? 'none' : '';
    }
}

function refreshControls() {
    let controlsElement = document.getElementById('controls-bar');
    if (controlsElement) {
        controlsElement.remove();
    }

    controlsElement = document.createElement('div');
    controlsElement.id = 'controls-bar';

    // Navigation controls
    let navControls = document.createElement('div');
    navControls.className = 'controls-group';
    navControls.id = 'nav-controls-container';

    let backButton = document.createElement('div');
    backButton.className = 'btn-disabled';
    backButton.id = 'btn-back';
    navControls.append(backButton);

    let forwardButton = document.createElement('div');
    forwardButton.className = 'btn-disabled';
    forwardButton.id = 'btn-forward';
    navControls.append(forwardButton);

    let reloadButton = document.createElement('div');
    reloadButton.className = 'btn';
    reloadButton.id = 'btn-reload';
    navControls.append(reloadButton);

    let homrButton = document.createElement('div');
    homrButton.className = 'btn';
    homrButton.id = 'btn-home';
    navControls.append(homrButton);

    let favoritesButton = document.createElement('div');
    favoritesButton.className = 'btn';
    favoritesButton.id = 'btn-favorites';
    navControls.append(favoritesButton);

    let printButton = document.createElement('div');
    printButton.className = 'btn';
    printButton.id = 'btn-print';
    navControls.append(printButton);

    let newWindowButton = document.createElement('div');
    newWindowButton.className = 'btn';
    newWindowButton.id = 'btn-new-window';
    navControls.append(newWindowButton);

    controlsElement.append(navControls);

    // Address bar
    let addressBar = document.createElement('div');
    addressBar.id = 'address-bar-container';

    let securityLabel = document.createElement('div');
    securityLabel.className = 'label-unknown';
    securityLabel.id = 'security-label';

    let labelSpan = document.createElement('span');
    //labelSpan.textContent = 'Not secure';
    securityLabel.append(labelSpan);

    let lockIcon = document.createElement('div');
    lockIcon.className = 'icn';
    lockIcon.id = 'icn-lock';
    securityLabel.append(lockIcon);
    addressBar.append(securityLabel);

    let addressInput = document.createElement('input');
    addressInput.id = 'address-field';
    addressInput.placeholder = '';
    addressInput.type = 'text';
    addressInput.spellcheck = false;
    addressBar.append(addressInput);

    let zoomField = document.createElement('div');
    zoomField.id = 'zoom-field';
    zoomField.textContent = '100%';
    zoomField.style.display = 'none';
    addressBar.append(zoomField);

    let timerField = document.createElement('div');
    timerField.id = 'inactivity-timer-field';
    timerField.textContent = '---';
    addressBar.append(timerField);

    let activityField = document.createElement('div');
    activityField.id = 'activity-timer-field';
    activityField.textContent = '---';
    activityField.style.display = 'none';
    addressBar.append(activityField);

    let favoriteButton = document.createElement('div');
    favoriteButton.className = 'icn';
    favoriteButton.id = 'btn-fav';
    addressBar.append(favoriteButton);
    controlsElement.append(addressBar);

    // Manage controls
    let manageControls = document.createElement('div');
    manageControls.className = 'controls-group';
    manageControls.id = 'manage-controls-container';

    let optionsButton = document.createElement('div');
    optionsButton.className = 'btn';
    optionsButton.id = 'btn-options';
    manageControls.append(optionsButton);
    controlsElement.append(manageControls);

    // Insert controls bar into document
    let bodyElement = document.getElementsByTagName('body')[0];
    bodyElement.append(controlsElement);

    addControlsListeners();
    updateNavigationUI();
}

function refreshTabs() {
    let tabsStrip = document.getElementById('tabs-strip');
    if (tabsStrip) {
        tabsStrip.remove();
    }

    tabsStrip = document.createElement('div');
    tabsStrip.id = 'tabs-strip';

    let newTabButton = document.createElement('div');
    newTabButton.id = 'btn-new-tab';

    let buttonSpan = document.createElement('span');
    buttonSpan.textContent = '+';
    buttonSpan.id = 'plus-label';
    newTabButton.append(buttonSpan);
    tabsStrip.append(newTabButton);

    // Window control buttons
    let windowControls = document.createElement('div');
    windowControls.id = 'window-controls';

    let minimizeBtn = document.createElement('div');
    minimizeBtn.className = 'btn-window';
    minimizeBtn.id = 'btn-window-minimize';
    minimizeBtn.innerHTML = '<svg viewBox="0 0 10 10"><line x1="1" y1="5" x2="9" y2="5"/></svg>';
    minimizeBtn.addEventListener('click', function() {
        window.chrome.webview.postMessage({ message: commands.MG_MINIMIZE, args: {} });
    });
    windowControls.append(minimizeBtn);

    let maximizeBtn = document.createElement('div');
    maximizeBtn.className = 'btn-window';
    maximizeBtn.id = 'btn-window-maximize';
    maximizeBtn.innerHTML = '<svg viewBox="0 0 10 10"><rect x="1" y="1" width="8" height="8" fill="none" stroke-width="1"/></svg>';
    maximizeBtn.addEventListener('click', function() {
        window.chrome.webview.postMessage({ message: commands.MG_MAXIMIZE, args: {} });
    });
    windowControls.append(maximizeBtn);

    let closeBtn = document.createElement('div');
    closeBtn.className = 'btn-window';
    closeBtn.id = 'btn-window-close';
    closeBtn.innerHTML = '<svg viewBox="0 0 10 10"><line x1="1" y1="1" x2="9" y2="9"/><line x1="9" y1="1" x2="1" y2="9"/></svg>';
    closeBtn.addEventListener('click', function() {
        window.chrome.webview.postMessage({ message: commands.MG_CLOSE_WINDOW, args: {} });
    });
    windowControls.append(closeBtn);

    tabsStrip.append(windowControls);

    tabsStrip.addEventListener('mousedown', function(e) {
        if (e.target === tabsStrip || e.target === newTabButton || e.target === buttonSpan) {
            if (!e.target.closest('#window-controls') && !e.target.closest('#btn-new-tab')) {
                window.chrome.webview.postMessage({ message: commands.MG_START_DRAG, args: {} });
            }
        }
    });

    let bodyElement = document.getElementsByTagName('body')[0];
    bodyElement.append(tabsStrip);

    addTabsListeners();

    Array.from(tabs).map((tabEntry) => {
        loadTabUI(tabEntry[0]);
    });
}

function importFileFavorites(fileFavorites) {
    let imported = 0;
    let total = fileFavorites.length;
    if (total === 0) return;

    fileFavorites.forEach((fav) => {
        isFavorite(fav.uri, (existing) => {
            if (!existing) {
                addFavorite(fav, () => { imported++; });
            }
        });
    });
}

function toggleFavorite() {
    activeTab = tabs.get(activeTabId);
    if (activeTab.isFavorite) {
        removeFavorite(activeTab.uri, () => {
            activeTab.isFavorite = false;
            updateFavoriteIcon();
        });
    } else {
        addFavorite(favoriteFromTab(activeTabId), () => {
            activeTab.isFavorite = true;
            updateFavoriteIcon();
        });
    }
}

function addControlsListeners() {
    addFavoritesButtonListener();
    let inputField = document.querySelector('#address-field');

    inputField.addEventListener('keydown', function(e) {
        var key = e.which || e.keyCode;
        if (key === 13 && e.ctrlKey && !settings.disableCtrlEnter) {
            e.preventDefault();
            var text = inputField.value.trim();
            if (text && !text.match(/^https?:\/\//)) {
                text = 'www.' + text + '.com';
            }
            processAddressBarInputValue(text);
            return;
        }
    });

    inputField.addEventListener('keypress', function(e) {
        var key = e.which || e.keyCode;
        if (key === 13) { // 13 is enter
            e.preventDefault();
            processAddressBarInput();
        }
    });

    inputField.addEventListener('focus', function(e) {
        e.target.select();
    });

    inputField.addEventListener('blur', function(e) {
        inputField.setSelectionRange(0, 0);
        if (!inputField.value) {
            updateURI();
        }
    });

    let zoomEl = document.getElementById('zoom-field');
    if (zoomEl) {
        zoomEl.style.cursor = 'pointer';
        zoomEl.addEventListener('click', function() {
            window.chrome.webview.postMessage({
                message: commands.MG_RESET_ZOOM,
                args: {}
            });
        });
    }

    document.querySelector('#btn-forward').addEventListener('click', function(e) {
        if (document.getElementById('btn-forward').className === 'btn') {
            var message = {
                message: commands.MG_GO_FORWARD,
                args: {}
            };
            window.chrome.webview.postMessage(message);
        }
    });

    document.querySelector('#btn-back').addEventListener('click', function(e) {
        if (document.getElementById('btn-back').className === 'btn') {
            var message = {
                message: commands.MG_GO_BACK,
                args: {}
            };
            window.chrome.webview.postMessage(message);
        }
    });

    document.querySelector('#btn-reload').addEventListener('click', function(e) {
        var btnReload = document.getElementById('btn-reload');
        if (btnReload.className === 'btn-cancel') {
            var message = {
                message: commands.MG_CANCEL,
                args: {}
            };
            window.chrome.webview.postMessage(message);
        } else if (btnReload.className === 'btn') {
            reloadActiveTabContent();
        }
    });

    document.querySelector('#btn-print').addEventListener('click', function(e) {
        var message = {
            message: commands.MG_PRINT,
            args: {}
        };
        window.chrome.webview.postMessage(message);
    });

    document.querySelector('#btn-new-window').addEventListener('click', function (e) {
      var message = {
        message: commands.MG_NEW_WINDOW,
        args: {}
      };
      window.chrome.webview.postMessage(message);
    });

    document.querySelector('#btn-home').addEventListener('click', function(e) {
        var message = {
            message: commands.MG_HOME,
            args: {}
        };
        window.chrome.webview.postMessage(message);
    });

    document.querySelector('#btn-favorites').addEventListener('click', function(e) {
        var message = {
            message: commands.MG_NAVIGATE,
            args: { uri: 'browser://favorites' }
        };
        window.chrome.webview.postMessage(message);
    });


    document.querySelector('#btn-options').addEventListener('click', function(e) {
        toggleOptionsDropdown();
    });

    // Prevent zooming the UI
    window.addEventListener('wheel', function(event) {
        if (event.ctrlKey) {
            event.preventDefault();
        }}, { passive: false });
}

function addTabsListeners() {
    document.querySelector('#btn-new-tab').addEventListener('click', function(e) {
        createNewTab(true);
    });
}

function addFavoritesButtonListener() {
    var favBtn = document.querySelector('#btn-fav');
    if (favBtn) {
        favBtn.addEventListener('click', function(e) {
            toggleFavorite();
        });
    }
}

function createContextMenu() {
    var menu = document.createElement('div');
    menu.id = 'context-menu';
    menu.style.display = 'none';

    var items = ['Cut', 'Copy', 'Paste'];
    items.forEach(function(item) {
        var btn = document.createElement('div');
        btn.className = 'context-menu-item';
        btn.textContent = item;
        btn.addEventListener('click', function(e) {
            e.stopPropagation();
            var field = document.getElementById('address-field');
            if (item === 'Cut') {
                document.execCommand('cut');
            } else if (item === 'Copy') {
                document.execCommand('copy');
            } else if (item === 'Paste') {
                navigator.clipboard.readText().then(function(text) {
                    document.execCommand('insertText', false, text);
                });
            }
            menu.style.display = 'none';
        });
        menu.appendChild(btn);
    });

    document.body.appendChild(menu);

    var field = document.getElementById('address-field');
    field.addEventListener('contextmenu', function(e) {
        e.preventDefault();
        var menuHeight = 80;
        var bodyHeight = document.body.clientHeight;
        var top = e.pageY;
        if (top + menuHeight > bodyHeight) {
            top = bodyHeight - menuHeight;
        }
        if (top < 0) top = 0;
        menu.style.left = e.pageX + 'px';
        menu.style.top = top + 'px';
        menu.style.display = 'block';
    });

    document.addEventListener('click', function() {
        menu.style.display = 'none';
    });
}

function init() {
    window.chrome.webview.addEventListener('message', messageHandler);
    refreshTabs();
    refreshControls();

    createNewTab(true);
    createContextMenu();
}

init();
