/// <reference path="..\..\GSMyAdmin\WebRoot\Scripts\UI.js" />
/// <reference path="..\..\GSMyAdmin\WebRoot\Scripts\API.js" />
/// <reference path="..\..\GSMyAdmin\WebRoot\Scripts\Common.js" />
/// <reference path="..\..\GSMyAdmin\WebRoot\Scripts\knockout-3.5.1.js" />

/* jshint undef: true, unused: false, eqnull: false */
/* global API,UI,PluginHandler,ko */
/* eslint eqeqeq: "off", curly: "error" */

this.plugin = {
    PreInit: function () {
        //Called prior to the plugins initialisation, before the tabs are loaded.
        //This method must not invoke any module/plugin specific API calls.
    },

    PostInit: function () {
        //The tabs have been loaded. You should wire up any event handlers here.
    },

    Reset: function () {

    },

    AMPDataLoaded: function (self) {
        setTimeout(backupListVM.checkScheduleWarning, 2000);
    },

    tabs: [
        {
            File: "Backups.html", //URL to fetch the tab contents from. Relative to the plugin WebRoot directory.
            ExternalTab: false,   //If True, 'File' is treated as an absolute URL to allow contents to be loaded from elsewhere.
            //Note that the appropriate CORS headers are required on the hosting server to allow this.
            ShortName: "Backups",    //Name used for the element. Prefixed with tab_PLUGINNAME_
            Name: "Backups",     //Display name for the tab.
            Icon: "database",            //Icon to show in the tab.
            Light: false,                //Use the 'light' theme for this tab.
            Category: "Settings",
            Click: () => { backupListVM.refresh(); },
            RequiredPermission: "LocalFileBackup.Backup.ViewBackupsList",
            Order: 20,
        }
    ]
};

this.stylesheet = "StyleSheet.css";    //Styles for tab-specific styles

function getFriendlySize(input) {
    const suffixes = ["B", "KB", "MB", "GB", "TB", "PB"];
    let index = 0;

    while (input > 1024 && index < 5) {
        input /= 1024;
        index++;
    }

    return input.toFixed(2) + " " + suffixes[index];
}

function backupEntryVM()
{
    const self = this;
    this.Id = ko.observable("");
    this.Name = ko.observable("");
    this.Description = ko.observable("");
    this.TakenBy = ko.observable("");
    this.TotalSizeBytes = ko.observable(0);
    this._displayTotalSize = ko.computed(() => getFriendlySize(self.TotalSizeBytes()));
    this.CompressedSizeBytes = ko.observable(0);
    this._displayCompressedSize = ko.computed(() => getFriendlySize(self.CompressedSizeBytes()));
    this.Sticky = ko.observable(false);
    this.Timestamp = ko.observable(0);
    this.StoredLocally = ko.observable(false);
    this.StoredRemotely = ko.observable(false);
    this._displayDate = ko.computed(() => parseDate(self.Timestamp()).toLocaleString());
    this._selected = ko.observable(false);
    this._vm = null;

    this.deleteBackup = async function () {
        const confirm = await UI.ShowModalAsync("Confirm Deletion", { text: "Are you sure you wish to delete this backup?", subtitle: self.Name() }, UI.Icons.Exclamation, [
            new UI.ModalAction("Delete Backup", true, "bgRed"),
            UI.CancelAction()
        ]);

        if (confirm) {
            await API.LocalFileBackupPlugin.DeleteBackupAsync(self.Id());
            self._vm.refresh();
        }
    };

    this.uploadToS3 = async function () {
        self.StoredRemotely(true); //Not really, but prevents this from being clicked again.
        const result = await API.LocalFileBackupPlugin.UploadToS3TaskAsync(self.Id());
        if (result.Status) {
            result.onComplete(self._vm.refresh);
        }
    };

    this.downloadFromS3 = async function () {
        self.StoredLocally(true); //Not really, but prevents from being clicked again.
        const result = await API.LocalFileBackupPlugin.DownloadFromS3TaskAsync(self.Id());
        if (result.Status) {
            result.onComplete(self._vm.refresh);
        }
    };

    this.deleteLocal = async function () {
        if (!(await UI.ShowModalAsync("Confirm Local Backup Deletion", `Are you sure you wish to delete the backup ${self.Name()} locally? ${(self.StoredRemotely() ? "A remote copy also exists on S3 storage." : "There is no remote copy available.")}`, UI.Icons.Exclamation, [
            new UI.ModalAction("Delete Local Backup", true, "bgRed"),
            UI.CancelAction()
        ]))) { return; }
        self.StoredLocally(false);
        await API.LocalFileBackupPlugin.DeleteLocalBackupAsync(self.Id());
        await self._vm.refresh();
    };

    this.deleteS3 = async function () {
        if (!(await UI.ShowModalAsync("Confirm Remote Backup Deletion", `Are you sure you wish to delete the backup ${self.Name()} remotely? ${(self.StoredLocally() ? "A local copy also exists." : "There is no local copy available.")}`, UI.Icons.Exclamation, [
            new UI.ModalAction("Delete Remote Backup", true, "bgRed"),
            UI.CancelAction()
        ]))) { return; }
        self.StoredRemotely(false);
        await API.LocalFileBackupPlugin.DeleteFromS3Async(self.Id());
        await self._vm.refresh();
    }

    this.restore = async function () {
        const confirm = await UI.ShowModalAsync("Confirm Restore", { text: "Are you sure you wish to restore this backup? Any files in this archive will overwrite any with the same name that already exist.", subtitle: self.Name() }, UI.Icons.Exclamation, [
            new UI.ModalAction("Restore Backup", true, "bgRed", true),
            UI.CancelAction()
        ]);

        if (confirm) {
            const result = await API.LocalFileBackupPlugin.RestoreBackupTaskAsync(self.Id(), false, self._vm.refresh);
            if (result.Status) {
                result.onComplete(self._vm.refresh);
            }
            else {
                await UI.ShowModalAsync("Unable to restore backup", result.Reason, UI.Icons.Exclamation, UI.OKActionOnly);
            }
        }
    };

    this.click = function () {
        const current = self._vm.selectedEntry();
        if (current != null) { current._selected(false); }

        self._selected(true);
        self._vm.selectedEntry(this);
    };
}

const backupListVM = new BackupsListVM();
function BackupsListVM()
{
    const self = this;
    const storageKey = `backup-notice.${viewModels.support.instanceId()}`;

    this.backups = ko.observableArray(); //of backupEntryVM
    this.newBackupDescription = ko.observable("");
    this.newBackupName = ko.observable("");
    this.newBackupSticky = ko.observable(false);
    this.selectedEntry = ko.observable(null);
    this.bindingsApplied = false;
    this.showScheduleWarning = ko.observable(false);
    this.dismissScheduleWarning = function () {
        const backupMenu = UI.GetSideMenuItem("tab_LocalFileBackupPlugin_Backups");
        backupMenu.subtitleIcon("");
        backupMenu.extraClass("");
        backupMenu.subtitle("");
        self.showScheduleWarning(false);
    };
    this.dismissForever = function () {
        localStorage[storageKey] = -1;
        self.dismissScheduleWarning();
    }
    this.addBackupTrigger = function () {
        self.dismissScheduleWarning();
        UI.GetSideMenuItem("tab_schedule").click();
        if (viewModels.schedule.populatedTriggers().length === 0) {
            viewModels.schedule.addNewTrigger();
            viewModels.schedule.newTriggerType(15);
        }
    };
    this.checkScheduleWarning = function () {
        if (viewModels.support.module() == "ADSModule" || viewModels.support.module() == "") { return; }

        if (localStorage[storageKey] == -1) { return; }

        const backupTasksExists = viewModels.schedule.populatedTriggers().some(t => t.Tasks().some(s => s.Description().contains("backup")));
        if (backupTasksExists) { return; }

        const backupMenu = UI.GetSideMenuItem("tab_LocalFileBackupPlugin_Backups");
        if (backupMenu == null) { return; }
        backupMenu.subtitleIcon("info");
        backupMenu.extraClass("hasNotice info");
        backupMenu.subtitle("No backup schedule");

        self.showScheduleWarning(true);
    };
    
    this.hasS3Permission = () => userHasPermission("Settings.LocalFileBackupPlugin.Cloud.UseS3Storage");

    this.showS3 = () => self.hasS3Permission() && currentSettings["LocalFileBackupPlugin.Cloud.UseS3Storage"]?.value();

    this.promptS3 = function () {
        if (!self.hasS3Permission()) { return; }
        currentSettings["LocalFileBackupPlugin.Cloud.UseS3Storage"].highlight();
    };
    
    this.takeBackup = async function () {
        const result = await API.LocalFileBackupPlugin.TakeBackupTaskAsync(this.newBackupName, this.newBackupDescription, this.newBackupSticky);
        if (result.Status) {
            result.onComplete(self.refresh);
        }
        else {
            await UI.ShowModalAsync("Unable to start backup", result.Reason, UI.Icons.Exclamation, UI.OKActionOnly);
        }
    };
    
    this.refresh = async function() {
        if (self._refreshing) return;
        self._refreshing = true;

        if (!self.bindingsApplied) {
            UI.ApplyVMBinding(self, document.getElementById("tab_LocalFileBackupPlugin_Backups"));
            self.bindingsApplied = true;
        }

        self.selectedEntry(null);
        self.backups.removeAll();
        const backups = await API.LocalFileBackupPlugin.GetBackupsAsync();
        ko.utils.arrayPushAll(self.backups, ko.quickmap.to(backupEntryVM, backups, false, { _vm: self }));

        self._refreshing = false;
    }
}
