var tabs = new Map();
var tabIdCounter = 0;
var activeTabId = 0;
const INVALID_TAB_ID = 0;

function getNewTabId() {
    return ++tabIdCounter;
}

function isValidTabId(tabId) {
    return tabId != INVALID_TAB_ID && tabs.has(tabId);
}

function createNewTab(shouldBeActive) {
    const tabId = getNewTabId();

    var message = {
        message: commands.MG_CREATE_TAB,
        args: {
            tabId: parseInt(tabId),
            active: shouldBeActive || false
        }
    };

    window.chrome.webview.postMessage(message);

    tabs.set(parseInt(tabId), {
        title: 'Loading...',
        uri: '',
        uriToShow: '',
        favicon: 'img/favicon.png',
        isFavorite: false,
        isLoading: false,
        canGoBack: false,
        canGoForward: false,
        securityState: 'unknown',
        historyItemId: INVALID_HISTORY_ID
    });

    loadTabUI(tabId);

    if (shouldBeActive) {
        switchToTab(tabId, false);
    }
}

function switchToTab(id, updateOnHost) {
    if (!id) {
        console.log('ID not provided');
        return;
    }

    // Check the tab to switch to is valid
    if (!isValidTabId(id)) {
        return;
    }

    // No need to switch if the tab is already active
    if (id == activeTabId) {
        return;
    }

    // Get the tab element to switch to
    var tab = document.getElementById(`tab-${id}`);
    if (!tab) {
        console.log(`Can't switch to tab ${id}: element does not exist`);
        return;
    }

    // Change the style for the previously active tab
    if (isValidTabId(activeTabId)) {
        const activeTabElement = document.getElementById(`tab-${activeTabId}`);

        // Check the previously active tab element does actually exist
        if (activeTabElement) {
            activeTabElement.className = activeTabElement.classList.contains('tab-no-close') ? 'tab tab-no-close' : 'tab';
        }
    }

    // Set tab as active, preserving tab-no-close class if present
    tab.className = tab.classList.contains('tab-no-close') ? 'tab-active tab-no-close' : 'tab-active';
    activeTabId = id;

    // Instruct host app to switch tab
    if (updateOnHost) {
        var message = {
            message: commands.MG_SWITCH_TAB,
            args: {
                tabId: parseInt(activeTabId)
            }
        };

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

    updateNavigationUI(commands.MG_SWITCH_TAB);
}

function closeTab(id) {
    // If closing tab was active, switch tab or close window
    if (id == activeTabId) {
        if (tabs.size == 1) {
            // Last tab is closing
            if (settings.disableLastTabCloseWindow) {
                // Do nothing — prevent closing last tab
                return;
            }
            // Send close tab message first, then close window
            tabs.delete(id);
            var msg = {
                message: commands.MG_CLOSE_TAB,
                args: { tabId: id }
            };
            window.chrome.webview.postMessage(msg);
            closeWindow();
            return;
        }

        // Other tabs are open, switch to rightmost tab
        var tabsEntries = Array.from(tabs.entries());
        var lastEntry = tabsEntries.pop();
        if (lastEntry[0] == id) {
            lastEntry = tabsEntries.pop();
        }
        switchToTab(lastEntry[0], true);
    }

    // Remove tab element
    var tabElement = document.getElementById(`tab-${id}`);
    if (tabElement) {
        tabElement.parentNode.removeChild(tabElement);
    }
    // Remove tab from map
    tabs.delete(id);

    // Update close button visibility for remaining tabs
    updateCloseButtonVisibility();

    var message = {
        message: commands.MG_CLOSE_TAB,
        args: {
            tabId: id
        }
    };

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

function updateCloseButtonVisibility() {
    if (!settings.disableLastTabCloseWindow) return;
    var tabsEntries = Array.from(tabs.entries());
    var hide = tabsEntries.length <= 1;
    tabsEntries.forEach(function(entry) {
        var tabElement = document.getElementById('tab-' + entry[0]);
        if (tabElement) {
            var btn = tabElement.querySelector('.btn-tab-close');
            if (btn) {
                btn.style.visibility = hide ? 'hidden' : '';
                btn.style.pointerEvents = hide ? 'none' : '';
            }
        }
    });
}

function updateFaviconURI(tabId, src) {
    let tab = tabs.get(tabId);
    if (tab.favicon != src) {
        let img = new Image();

        // Update favicon element on successful load
        img.onload = () => {
            console.log('Favicon loaded');
            tab.favicon = src;

            if (tabId == activeTabId) {
                updatedFaviconURIHandler(tabId, tab);
            }
        };

        if (src) {
            // Try load from root on failed load
            img.onerror = () => {
                console.log('Cannot load favicon from link, trying with root');
                updateFaviconURI(tabId, '');
            };
        } else {
            // No link for favicon, try loading from root
            try {
                let tabURI = new URL(tab.uri);
                src = `${tabURI.origin}/favicon.ico`;
            } catch(e) {
                console.log(`Could not parse tab ${tabId} URI`);
            }

            img.onerror = () => {
                console.log('No favicon in site root. Using default favicon.');
                tab.favicon = 'img/favicon.png';
                updatedFaviconURIHandler(tabId, tab);
            };
        }

        img.src = src;
    }
}

function updatedFaviconURIHandler(tabId, tab) {
    updateNavigationUI(commands.MG_UPDATE_FAVICON);

    // Update favicon in history item
    if (tab.historyItemId != INVALID_HISTORY_ID) {
        updateHistoryItem(tab.historyItemId, historyItemFromTab(tabId));
    }
}

function favoriteFromTab(tabId) {
    if (!isValidTabId(tabId)) {
        console.log('Invalid tab ID');
        return;
    }

    let tab = tabs.get(tabId);
    let favicon = tab.favicon == 'img/favicon.png' ? '../controls_ui/' + tab.favicon : tab.favicon;
    return {
        uri: tab.uri,
        uriToShow: tab.uriToShow,
        title: tab.title,
        favicon: favicon
    };
}

function historyItemFromTab(tabId) {
    if (!isValidTabId(tabId)) {
        console.log('Invalid tab ID');
        return;
    }

    let tab = tabs.get(tabId);
    let favicon = tab.favicon == 'img/favicon.png' ? '../controls_ui/' + tab.favicon : tab.favicon;
    return {
        uri: tab.uri,
        title: tab.title,
        favicon: favicon,
        timestamp: new Date()
    }
}
