'use strict';

/* global angular:false */
/* global $:false */

angular.module('Application').controller('SettingsController', ['$scope', '$location', '$translate', '$rootScope', '$timeout', 'Client', function ($scope, $location, $translate, $rootScope, $timeout, Client) {
    Client.onReady(function () { if (!Client.getUserInfo().isAtLeastAdmin) $location.path('/'); });

    $scope.client = Client;
    $scope.user = Client.getUserInfo();
    $scope.config = Client.getConfig();
    $scope.installedApps = Client.getInstalledApps();

    $scope.subscription = null;
    $scope.subscriptionBusy = true;

    // values correspond to cron days
    $scope.cronDays = [
        { name: 'Sunday', value: 0 },
        { name: 'Monday', value: 1 },
        { name: 'Tuesday', value: 2 },
        { name: 'Wednesday', value: 3 },
        { name: 'Thursday', value: 4 },
        { name: 'Friday', value: 5 },
        { name: 'Saturday', value: 6 },
    ];

    $scope.cronHours = [
        { name: 'Midnight', value: 0 }, { name: '1 AM', value: 1 }, { name: '2 AM', value: 2 }, { name: '3 AM', value: 3 },
        { name: '4 AM', value: 4 }, { name: '5 AM', value: 5 }, { name: '6 AM', value: 6 }, { name: '7 AM', value: 7 },
        { name: '8 AM', value: 8 }, { name: '9 AM', value: 9 }, { name: '10 AM', value: 10 }, { name: '11 AM', value: 11 },
        { name: 'Noon', value: 12 }, { name: '1 PM', value: 13 }, { name: '2 PM', value: 14 }, { name: '3 PM', value: 15 },
        { name: '4 PM', value: 16 }, { name: '5 PM', value: 17 }, { name: '6 PM', value: 18 }, { name: '7 PM', value: 19 },
        { name: '8 PM', value: 20 }, { name: '9 PM', value: 21 }, { name: '10 PM', value: 22 }, { name: '11 PM', value: 23 }
    ];

    $scope.registryConfigProviders = [
        { name: 'AWS', value: 'aws' },
        { name: 'Digital Ocean', value: 'digitalocean' },
        { name: 'DockerHub', value: 'dockerhub' },
        { name: 'Google Cloud', value: 'google-cloud' },
        { name: 'Linode', value: 'linode' },
        { name: 'Other', value: 'other' },
        { name: 'Quay', value: 'quay' },
        { name: 'Treescale', value: 'treescale' },
        { name: 'Disabled', value: 'noop' }
    ];

    $scope.openSubscriptionSetup = function () {
        Client.openSubscriptionSetup($scope.subscription || {});
    };

    $scope.prettyProviderName = function (provider) {
        switch (provider) {
        case 'caas': return 'Managed Cloudron';
        default: return provider;
        }
    };

    $scope.prettyAutoUpdateSchedule = function (pattern) {
        if (!pattern) return '';
        var tmp = pattern.split(' ');

        if (tmp.length === 1) return tmp[0];

        var hours = tmp[2].split(',');
        var days = tmp[5].split(',');
        var prettyDay;
        if (days.length === 7 || days[0] === '*') {
            prettyDay = 'Everyday';
        } else  {
            prettyDay = days.map(function (day) { return $scope.cronDays[parseInt(day, 10)].name.substr(0, 3); }).join(',');
        }

        try {
            var prettyHour = hours.map(function (hour) { return $scope.cronHours[parseInt(hour, 10)].name; }).join(',');

            return prettyDay + ' at ' + prettyHour;
        } catch (error) {
            return 'Custom pattern';
        }
    };

    $scope.update = {
        error: {}, // this is for the dialog
        busy: false,
        checking: false,
        percent: 0,
        message: 'Downloading',
        errorMessage: '', // this shows inline
        taskId: '',
        skipBackup: false,

        checkNow: function () {
            $scope.update.checking = true;

            Client.checkForUpdates(function (error) {
                if (error) Client.error(error);

                $scope.update.checking = false;
            });
        },

        show: function () {
            $scope.update.error.generic = null;
            $scope.update.busy = false;

            $('#updateModal').modal('show');
        },

        stopUpdate: function () {
            Client.stopTask($scope.update.taskId, function (error) {
                if (error) {
                    if (error.statusCode === 409) {
                        $scope.update.errorMessage = 'No update is currently in progress';
                    } else {
                        console.error(error);
                        $scope.update.errorMessage = error.message;
                    }

                    $scope.update.busy = false;

                    return;
                }
            });
        },

        checkStatus: function () {
            Client.getLatestTaskByType('update', function (error, task) {
                if (error) return console.error(error);
                if (!task) return;

                $scope.update.taskId = task.id;
                $scope.update.updateStatus();
            });
        },

        reloadIfNeeded: function () {
            Client.getStatus(function (error, status) {
                if (error) return $scope.error(error);

                if (window.localStorage.version !== status.version) window.location.reload(true);
            });
        },

        updateStatus: function () {
            Client.getTask($scope.update.taskId, function (error, data) {
                if (error) return window.setTimeout($scope.update.updateStatus, 5000);

                if (!data.active) {
                    $scope.update.busy = false;
                    $scope.update.message = '';
                    $scope.update.percent = 100; // indicates that 'result' is valid
                    $scope.update.errorMessage = data.success ? '' : data.error.message;

                    if (!data.errorMessage) $scope.update.reloadIfNeeded(); // assume success

                    return;
                }

                $scope.update.busy = true;
                $scope.update.percent = data.percent;
                $scope.update.message = data.message;

                window.setTimeout($scope.update.updateStatus, 500);
            });
        },

        startUpdate: function () {
            $scope.update.error.generic = null;
            $scope.update.busy = true;
            $scope.update.percent = 0;
            $scope.update.message = '';
            $scope.update.errorMessage = '';

            Client.update({ skipBackup: $scope.update.skipBackup }, function (error, taskId) {
                if (error) {
                    $scope.update.error.generic = error.message;
                    $scope.update.busy = false;
                    return;
                }

                $('#updateModal').modal('hide');

                $scope.update.taskId = taskId;
                $scope.update.updateStatus();
            });
        }
    };

    $scope.timeZone = {
        busy: false,
        success: false,
        error: '',
        timeZone: '',
        currentTimeZone: '',
        availableTimeZones: window.timezones,

        submit: function () {
            if ($scope.timeZone.timeZone === $scope.timeZone.currentTimeZone) return;

            $scope.timeZone.error = '';
            $scope.timeZone.busy = true;
            $scope.timeZone.success = false;

            Client.setTimeZone($scope.timeZone.timeZone.id, function (error) {
                if (error) $scope.timeZone.error = error.message;
                else $scope.timeZone.currentTimeZone = $scope.timeZone.timeZone;

                $timeout(function () {
                    $scope.timeZone.busy = false;
                    $scope.timeZone.success = true;
                }, 2000); // otherwise, it's too fast
            });
        }
    };

    $scope.language = {
        busy: false,
        success: false,
        error: '',
        language: '',
        currentLanguage: '',
        availableLanguages: Client.getAvailableLanguages(),

        submit: function () {
            if ($scope.language.language === $scope.language.currentLanguage) return;

            $scope.language.error = '';
            $scope.language.busy = true;
            $scope.language.success = false;

            Client.setLanguage($scope.language.language.id, function (error) {
                if (error) $scope.language.error = error.message;
                else $scope.language.currentLanguage = $scope.language.language;

                $timeout(function () {
                    $scope.language.busy = false;
                    $scope.language.success = true;
                }, 2000); // otherwise, it's too fast
            });
        }
    };

    $scope.updateSchedule = {
        busy: false,
        currentPattern: '',
        days: [],
        hours: [],
        type: 'pattern',

        isScheduleValid: function () {
            return $scope.updateSchedule.hours.length !== 0 && $scope.updateSchedule.days !== 0;
        },

        show: function () {
            $scope.updateSchedule.busy = false;

            if ($scope.updateSchedule.currentPattern === 'never') {
                $scope.updateSchedule.type = 'never';
                $scope.updateSchedule.days = [];
                $scope.updateSchedule.hours = [];
            } else {
                $scope.updateSchedule.type = 'pattern';

                var tmp = $scope.updateSchedule.currentPattern.split(' ');
                var hours = tmp[2].split(','), days = tmp[5].split(',');
                if (days[0] === '*') {
                    $scope.updateSchedule.days = angular.copy($scope.cronDays, []);
                } else {
                    $scope.updateSchedule.days = days.map(function (day) { return $scope.cronDays[parseInt(day, 10)]; });
                }
                try {
                    $scope.updateSchedule.hours = hours.map(function (hour) { return $scope.cronHours[parseInt(hour, 10)]; });
                } catch (e) {
                    console.error('Error parsing hour');
                }
            }

            $('#updateScheduleModal').modal('show');
        },

        submit: function () {
            var pattern = 'never';
            if ($scope.updateSchedule.type === 'pattern') {
                var daysPattern;
                if ($scope.updateSchedule.days.length === 7) daysPattern = '*';
                else daysPattern = $scope.updateSchedule.days.map(function (d) { return d.value; });

                var hoursPattern;
                if ($scope.updateSchedule.hours.length === 24) hoursPattern = '*';
                else hoursPattern = $scope.updateSchedule.hours.map(function (d) { return d.value; });

                pattern ='00 00 ' + hoursPattern + ' * * ' + daysPattern;
            }

            $scope.updateSchedule.busy = true;

            Client.setAutoupdatePattern(pattern, function (error) {
                if (error) Client.error(error);

                $timeout(function () {
                    $scope.updateSchedule.busy = false;
                    if (!error) $scope.updateSchedule.currentPattern = pattern;
                    $('#updateScheduleModal').modal('hide');
                }, 3000);
            });
        }
    };

    function getTimeZone() {
        Client.getTimeZone(function (error, timeZone) {
            if (error) return console.error(error);

            $scope.timeZone.currentTimeZone = window.timezones.find(function (t) { return t.id === timeZone; });
            $scope.timeZone.timeZone = $scope.timeZone.currentTimeZone;
        });
    }

    function getAutoupdatePattern() {
        Client.getAutoupdatePattern(function (error, result) {
            if (error) return console.error(error);

            // just keep the UI sane by supporting previous default pattern
            if (result.pattern === '00 30 1,3,5,23 * * *') result.pattern = '00 15 1,3,5,23 * * *';

            $scope.updateSchedule.currentPattern = result.pattern;
            $scope.updateSchedule.pattern = result.pattern;
        });
    }

    function getRegistryConfig() {
        Client.getRegistryConfig(function (error, result) {
            if (error) return console.error(error);

            $scope.registryConfig.currentConfig = result;
        });
    }

    function getSubscription() {
        $scope.subscriptionBusy = true;

        Client.getSubscription(function (error, result) {
            $scope.subscriptionBusy = false;

            if (error && error.statusCode === 412) return; // not yet registered
            if (error) return console.error(error);

            $scope.subscription = result;
        });
    }

    $scope.registryConfig = {
        busy: false,
        error: null,
        serverAddress: '',
        provider: 'noop',
        username: '',
        password: '',
        email: '',
        currentConfig: {},

        reset: function () {
            $scope.registryConfig.busy = false;
            $scope.registryConfig.error = null;

            $scope.registryConfig.provider = $scope.registryConfig.currentConfig.provider;
            $scope.registryConfig.serverAddress = $scope.registryConfig.currentConfig.serverAddress || '';
            $scope.registryConfig.username = $scope.registryConfig.currentConfig.username || '';
            $scope.registryConfig.email = $scope.registryConfig.currentConfig.email || '';
            $scope.registryConfig.password = $scope.registryConfig.currentConfig.password || '';

            $scope.registryConfigForm.$setUntouched();
            $scope.registryConfigForm.$setPristine();
        },

        show: function () {
            $scope.registryConfig.reset();
            $('#registryConfigModal').modal('show');
        },

        submit: function () {
            $scope.registryConfig.busy = true;

            var data = {
                provider: $scope.registryConfig.provider
            };

            if ($scope.registryConfig.provider !== 'noop') {
                data.serverAddress = $scope.registryConfig.serverAddress;
                data.username = $scope.registryConfig.username || '';
                data.password = $scope.registryConfig.password;
                data.email = $scope.registryConfig.email || '';
            }

            Client.setRegistryConfig(data, function (error) {
                $scope.registryConfig.busy = false;

                if (error) {
                    $scope.registryConfig.error = error.message;
                    return;
                }

                $('#registryConfigModal').modal('hide');

                getRegistryConfig();
            });
        }
    };

    Client.onReady(function () {
        getAutoupdatePattern();
        getRegistryConfig();
        getTimeZone();

        $translate.onReady(function () {
            Client.getLanguage(function (error, usedLang) {
                if (error) return console.error('Unable to fetch language:', error);

                $scope.language.availableLanguages = Client.getAvailableLanguages().map(function (l) {
                    return {
                        // we only show those in english for easier restore
                        display: $translate.instant('lang.'+l, {}, undefined, 'en'),
                        id: l
                    };
                });
                $scope.language.currentLanguage = $scope.language.availableLanguages.find(function (l) { return l.id === usedLang; });
                $scope.language.language = $scope.language.currentLanguage;
            });
        });

        $scope.update.checkStatus();

        if ($scope.user.isAtLeastOwner) getSubscription();
    });

    // setup all the dialog focus handling
    ['planChangeModal', 'appstoreLoginModal'].forEach(function (id) {
        $('#' + id).on('shown.bs.modal', function () {
            $(this).find("[autofocus]:first").focus();
        });
    });

    $('.modal-backdrop').remove();
}]);
