"use strict";

import protectedSessionHolder from '../services/protected_session_holder.js';
import server from '../services/server.js';
import infoService from "../services/info.js";
import zoomService from "../services/zoom.js";
import utils from "../services/utils.js";
import cssLoader from "../services/css_loader.js";
import optionsInit from "../services/options_init.js";

const $dialog = $("#options-dialog");

const tabHandlers = [];

function addTabHandler(handler) {
    tabHandlers.push(handler);
}

async function showDialog() {
    glob.activeDialog = $dialog;

    const options = await server.get('options');

    $dialog.modal();

    for (const handler of tabHandlers) {
        if (handler.optionsLoaded) {
            handler.optionsLoaded(options);
        }
    }
}

async function saveOptions(options) {
    await server.put('options', options);

    infoService.showMessage("Options change have been saved.");
}

export default {
    showDialog,
    saveOptions
};

addTabHandler((function() {
    const $themeSelect = $("#theme-select");
    const $zoomFactorSelect = $("#zoom-factor-select");
    const $oneTabDisplaySelect = $("#one-tab-display-select");
    const $leftPaneMinWidth = $("#left-pane-min-width");
    const $leftPaneWidthPercent = $("#left-pane-width-percent");
    const $mainFontSize = $("#main-font-size");
    const $treeFontSize = $("#tree-font-size");
    const $detailFontSize = $("#detail-font-size");
    const $body = $("body");
    const $container = $("#container");

    async function optionsLoaded(options) {
        const themes = [
            { val: 'white', title: 'White' },
            { val: 'dark', title: 'Dark' },
            { val: 'black', title: 'Black' }
        ].concat(await server.get('options/user-themes'));

        $themeSelect.empty();

        for (const theme of themes) {
            $themeSelect.append($("<option>")
                .attr("value", theme.val)
                .attr("data-note-id", theme.noteId)
                .html(theme.title));
        }

        $themeSelect.val(options.theme);

        if (utils.isElectron()) {
            $zoomFactorSelect.val(options.zoomFactor);
        }
        else {
            $zoomFactorSelect.prop('disabled', true);
        }

        $oneTabDisplaySelect.val(options.hideTabRowForOneTab === 'true' ? 'hide' : 'show');

        $leftPaneMinWidth.val(options.leftPaneMinWidth);
        $leftPaneWidthPercent.val(options.leftPaneWidthPercent);

        $mainFontSize.val(options.mainFontSize);
        $treeFontSize.val(options.treeFontSize);
        $detailFontSize.val(options.detailFontSize);
    }

    $themeSelect.change(function() {
        const newTheme = $(this).val();

        for (const clazz of Array.from($body[0].classList)) { // create copy to safely iterate over while removing classes
            if (clazz.startsWith("theme-")) {
                $body.removeClass(clazz);
            }
        }

        const noteId = $(this).find(":selected").attr("data-note-id");

        if (noteId) {
            // make sure the CSS is loaded
            // if the CSS has been loaded and then updated then the changes won't take effect though
            cssLoader.requireCss(`/api/notes/download/${noteId}`);
        }

        $body.addClass("theme-" + newTheme);

        server.put('options/theme/' + newTheme);
    });

    $zoomFactorSelect.change(function() { zoomService.setZoomFactorAndSave($(this).val()); });

    function resizeLeftPanel() {
        const leftPanePercent = parseInt($leftPaneWidthPercent.val());
        const rightPanePercent = 100 - leftPanePercent;
        const leftPaneMinWidth = $leftPaneMinWidth.val();

        $container.css("grid-template-columns", `minmax(${leftPaneMinWidth}px, ${leftPanePercent}fr) ${rightPanePercent}fr`);
    }

    $oneTabDisplaySelect.change(function() {
        const hideTabRowForOneTab = $(this).val() === 'hide' ? 'true' : 'false';

        server.put('options/hideTabRowForOneTab/' + hideTabRowForOneTab)
            .then(optionsInit.loadOptions);
    });

    $leftPaneMinWidth.change(async function() {
        await server.put('options/leftPaneMinWidth/' + $(this).val());

        resizeLeftPanel();
    });

    $leftPaneWidthPercent.change(async function() {
        await server.put('options/leftPaneWidthPercent/' + $(this).val());

        resizeLeftPanel();
    });

    function applyFontSizes() {
        console.log($mainFontSize.val() + "% !important");

        $body.get(0).style.setProperty("--main-font-size", $mainFontSize.val() + "%");
        $body.get(0).style.setProperty("--tree-font-size", $treeFontSize.val() + "%");
        $body.get(0).style.setProperty("--detail-font-size", $detailFontSize.val() + "%");
    }

    $mainFontSize.change(async function() {
        await server.put('options/mainFontSize/' + $(this).val());

        applyFontSizes();
    });

    $treeFontSize.change(async function() {
        await server.put('options/treeFontSize/' + $(this).val());

        applyFontSizes();
    });

    $detailFontSize.change(async function() {
        await server.put('options/detailFontSize/' + $(this).val());

        applyFontSizes();
    });

    return {
        optionsLoaded
    };
})());

addTabHandler((function() {
    const $form = $("#change-password-form");
    const $oldPassword = $("#old-password");
    const $newPassword1 = $("#new-password1");
    const $newPassword2 = $("#new-password2");

    function optionsLoaded(options) {
    }

    $form.submit(() => {
        const oldPassword = $oldPassword.val();
        const newPassword1 = $newPassword1.val();
        const newPassword2 = $newPassword2.val();

        $oldPassword.val('');
        $newPassword1.val('');
        $newPassword2.val('');

        if (newPassword1 !== newPassword2) {
            alert("New passwords are not the same.");
            return false;
        }

        server.post('password/change', {
            'current_password': oldPassword,
            'new_password': newPassword1
        }).then(result => {
            if (result.success) {
                alert("Password has been changed. Trilium will be reloaded after you press OK.");

                // password changed so current protected session is invalid and needs to be cleared
                protectedSessionHolder.resetProtectedSession();
            }
            else {
                infoService.showError(result.message);
            }
        });

        return false;
    });

    return {
        optionsLoaded
    };
})());

addTabHandler((function() {
    const $form = $("#protected-session-timeout-form");
    const $protectedSessionTimeout = $("#protected-session-timeout-in-seconds");

    function optionsLoaded(options) {
        $protectedSessionTimeout.val(options['protectedSessionTimeout']);
    }

    $form.submit(() => {
        const protectedSessionTimeout = $protectedSessionTimeout.val();

        saveOptions({ 'protectedSessionTimeout': protectedSessionTimeout }).then(() => {
            optionsInit.loadOptions();
        });

        return false;
    });

    return {
        optionsLoaded
    };
})());

addTabHandler((function () {
    const $form = $("#note-revision-snapshot-time-interval-form");
    const $timeInterval = $("#note-revision-snapshot-time-interval-in-seconds");

    function optionsLoaded(options) {
        $timeInterval.val(options['noteRevisionSnapshotTimeInterval']);
    }

    $form.submit(() => {
        saveOptions({ 'noteRevisionSnapshotTimeInterval': $timeInterval.val() });

        return false;
    });

    return {
        optionsLoaded
    };
})());

addTabHandler((function() {
    const $form = $("#sync-setup-form");
    const $syncServerHost = $("#sync-server-host");
    const $syncServerTimeout = $("#sync-server-timeout");
    const $syncProxy = $("#sync-proxy");
    const $testSyncButton = $("#test-sync-button");

    function optionsLoaded(options) {
        $syncServerHost.val(options['syncServerHost']);
        $syncServerTimeout.val(options['syncServerTimeout']);
        $syncProxy.val(options['syncProxy']);
    }

    $form.submit(() => {
        saveOptions({
            'syncServerHost': $syncServerHost.val(),
            'syncServerTimeout': $syncServerTimeout.val(),
            'syncProxy': $syncProxy.val()
        });

        return false;
    });

    $testSyncButton.click(async () => {
        const result = await server.post('sync/test');

        if (result.success) {
            infoService.showMessage(result.message);
        }
        else {
            infoService.showError("Sync server handshake failed, error: " + result.message);
        }
    });

    return {
        optionsLoaded
    };
})());

addTabHandler((async function () {
    const $forceFullSyncButton = $("#force-full-sync-button");
    const $fillSyncRowsButton = $("#fill-sync-rows-button");
    const $anonymizeButton = $("#anonymize-button");
    const $cleanupSoftDeletedButton = $("#cleanup-soft-deleted-items-button");
    const $cleanupUnusedImagesButton = $("#cleanup-unused-images-button");
    const $vacuumDatabaseButton = $("#vacuum-database-button");

    $forceFullSyncButton.click(async () => {
        await server.post('sync/force-full-sync');

        infoService.showMessage("Full sync triggered");
    });

    $fillSyncRowsButton.click(async () => {
        await server.post('sync/fill-sync-rows');

        infoService.showMessage("Sync rows filled successfully");
    });


    $anonymizeButton.click(async () => {
        await server.post('anonymization/anonymize');

        infoService.showMessage("Created anonymized database");
    });

    $cleanupSoftDeletedButton.click(async () => {
        if (confirm("Do you really want to clean up soft-deleted items?")) {
            await server.post('cleanup/cleanup-soft-deleted-items');

            infoService.showMessage("Soft deleted items have been cleaned up");
        }
    });

    $cleanupUnusedImagesButton.click(async () => {
        if (confirm("Do you really want to clean up unused images?")) {
            await server.post('cleanup/cleanup-unused-images');

            infoService.showMessage("Unused images have been cleaned up");
        }
    });

    $vacuumDatabaseButton.click(async () => {
        await server.post('cleanup/vacuum-database');

        infoService.showMessage("Database has been vacuumed");
    });

    return {};
})());