'use strict';

const contextMenuItems = [
    { title: tr('contextMenuFillUsernameAndPassword'), action: 'fill_username_password' },
    { title: tr('contextMenuFillPassword'), action: 'fill_password' },
    { title: tr('contextMenuFillTOTP'), action: 'fill_totp' },
    { title: tr('contextMenuFillAttribute'), id: 'fill_attribute', visible: false },
    { title: tr('contextMenuShowPasswordGenerator'), action: 'show_password_generator' },
    { title: tr('contextMenuSaveCredentials'), action: 'save_credentials' },
    { title: tr('contextMenuRequestGlobalAutoType'), action: 'request_autotype' }
];

const initListeners = async function() {
    /**
     * Detects page redirects and increases the count. Count is reset after a normal navigation event.
     * Form submit is counted as one.
     * @param {object} details
     */
    browser.webNavigation.onCommitted.addListener((details) => {
        if (details.transitionQualifiers?.[0] === 'client_redirect' || details.transitionType === 'form_submit') {
            page.redirectCount += 1;
            return;
        }

        // Clear credentials on reload so a new retrieval can be made
        if (details.transitionType === 'reload') {
            page.clearLogins(details.tabId);
        }

        page.redirectCount = 0;
    });

    // Main event listener
    browser.runtime.onMessage.addListener(kpxcEvent.onMessage);

    // Listen for keyboard shortcuts specified by user
    browser.commands.onCommand.addListener(async (command) => {
        if (contextMenuItems.some(e => e.action === command)
            || command === 'redetect_fields'
            || command === 'choose_credential_fields'
            || command === 'retrieve_credentials_forced'
            || command === 'reopen_database'
            || command === 'reload_extension') {
            const tab = await getCurrentTab();
            if (tab?.id) {
                browser.tabs.sendMessage(tab.id, { action: command });
            }
        }
    });

    browser.contextMenus.onClicked.addListener(async (item, tab) => {
        if (!tab?.id) {
            return;
        }

        if (item?.menuItemId?.startsWith('fill_attribute')) {
            const menuItem = page.attributeMenuItems.find(i => i?.action === item?.menuItemId);
            if (menuItem) {
                browser.tabs.sendMessage(tab.id, {
                    action: 'fill_attribute',
                    args: menuItem?.args
                }, {
                    frameId: item.frameId
                }).catch((err) => {
                    logError(err);
                });
            }

            return;
        }

        browser.tabs.sendMessage(tab.id, {
            action: item.menuItemId
        }, {
            frameId: item.frameId
        }).catch((err) => {
            logError(err);
        });
    });

    // Show getting started page after first install
    browser.runtime.onInstalled.addListener((details) => {
        if (details?.reason === 'install') {
            browser.tabs.create({
                url: 'options/getting_started.html',
            });
        }
    });
};

const initContextMenuItems = async function() {
    page.menuContexts = [ 'editable' ];
    if (page.isFirefox) {
        page.menuContexts.push('password');
    }

    // Create context menu items
    await browser.contextMenus.removeAll();
    for (const item of contextMenuItems) {
        try {
            await browser.contextMenus.create({
                title: item.title,
                contexts: page.menuContexts,
                visible: item.visible,
                id: item.id || item.action
            });
        } catch (e) {
            logError(e);
        }
    }
};

(async () => {
    try {
        await keepass.migrateKeyRing();
        await page.initBrowser();
        await page.initSettings();
        await page.initSitePreferences();
        await tabs.initOpenedTabs();
        await tabs.initListeners();
        await initListeners();
        await initContextMenuItems();
        await httpAuth.init();
        await keepass.reconnect(null, 5000); // 5 second timeout for the first connect
        await keepass.enableAutomaticReconnect();
        await keepass.updateDatabase();
    } catch (e) {
        logError(`init.js failed: ${e}`);
    }
})();
