'use strict';

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

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

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

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

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

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

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

            if (!$scope.config.update.box.sourceTarballUrl) {
                $('#setupSubscriptionModal').modal('show');
            } else {
                $('#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.avatarChange = {
        busy: false,
        error: {},
        avatar: null,
        availableAvatars: [{
            file: null,
            data: null,
            url: '/img/avatars/avatar_0.png',
        }, {
            file: null,
            data: null,
            url: '/img/avatars/rubber-duck.png'
        }, {
            file: null,
            data: null,
            url: '/img/avatars/carrot.png'
        }, {
            file: null,
            data: null,
            url: '/img/avatars/cup.png'
        }, {
            file: null,
            data: null,
            url: '/img/avatars/football.png'
        }, {
            file: null,
            data: null,
            url: '/img/avatars/owl.png'
        }, {
            file: null,
            data: null,
            url: '/img/avatars/space-rocket.png'
        }, {
            file: null,
            data: null,
            url: '/img/avatars/armchair.png'
        }, {
            file: null,
            data: null,
            url: '/img/avatars/cap.png'
        }, {
            file: null,
            data: null,
            url: '/img/avatars/pan.png'
        }, {
            file: null,
            data: null,
            url: '/img/avatars/meat.png'
        }, {
            file: null,
            data: null,
            url: '/img/avatars/umbrella.png'
        }, {
            file: null,
            data: null,
            url: '/img/avatars/jar.png'
        }],

        getBlobFromImg: function (img, callback) {
            var size = 256;

            var canvas = document.createElement('canvas');
            canvas.width = size;
            canvas.height = size;

            var imageDimensionRatio = img.width / img.height;
            var canvasDimensionRatio = canvas.width / canvas.height;
            var renderableHeight, renderableWidth, xStart, yStart;

            if (imageDimensionRatio > canvasDimensionRatio) {
                renderableHeight = canvas.height;
                renderableWidth = img.width * (renderableHeight / img.height);
                xStart = (canvas.width - renderableWidth) / 2;
                yStart = 0;
            } else if (imageDimensionRatio < canvasDimensionRatio) {
                renderableWidth = canvas.width;
                renderableHeight = img.height * (renderableWidth / img.width);
                xStart = 0;
                yStart = (canvas.height - renderableHeight) / 2;
            } else {
                renderableHeight = canvas.height;
                renderableWidth = canvas.width;
                xStart = 0;
                yStart = 0;
            }

            var ctx = canvas.getContext('2d');
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            ctx.drawImage(img, xStart, yStart, renderableWidth, renderableHeight);

            canvas.toBlob(callback);
        },

        doChangeAvatar: function () {
            $scope.avatarChange.error.avatar = null;
            $scope.avatarChange.busy = true;

            var img = document.getElementById('previewAvatar');
            $scope.avatarChange.avatar.file = $scope.avatarChange.getBlobFromImg(img, function (blob) {
                Client.changeCloudronAvatar(blob, function (error) {
                    if (error) {
                        console.error('Unable to change cloudron avatar.', error);
                    } else {
                        Client.resetAvatar();
                    }

                    $('#avatarChangeModal').modal('hide');
                    $scope.avatarChange.avatarChangeReset();
                });
            });
        },

        setPreviewAvatar: function (avatar) {
            $scope.avatarChange.avatar = avatar;
        },

        avatarChangeReset: function () {
            $scope.avatarChange.error.avatar = null;
            $scope.avatarChange.avatar = null;
            $scope.avatarChange.busy = false;
        },

        showChangeAvatar: function () {
            $scope.avatarChange.avatarChangeReset();
            $('#avatarChangeModal').modal('show');
        },

        showCustomAvatarSelector: function () {
            $('#avatarFileInput').click();
        }
    };

    $scope.s3like = function (provider) {
        return provider === 's3' || provider === 'minio' || provider === 's3-v4-compat' || provider === 'exoscale-sos' || provider === 'digitalocean-spaces';
    };

    $scope.autoUpdate = {
        busy: false,
        success: false,
        error: '',
        pattern: '',
        currentPattern: '',

        checkNow: function () {
            $scope.autoUpdate.busy = true;

            Client.checkForUpdates(function (error) {
                if (error) $scope.autoUpdate.error = error.message;

                $scope.autoUpdate.busy = false;
            });
        },

        submit: function () {
            if ($scope.autoUpdate.pattern === $scope.autoUpdate.currentPattern) return;

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

            Client.setAppAutoupdatePattern($scope.autoUpdate.pattern, function (error) {
                if (error) $scope.autoUpdate.error = error.message;
                else $scope.autoUpdate.currentPattern = $scope.autoUpdate.pattern;

                $scope.autoUpdate.busy = false;
                $scope.autoUpdate.success = true;
            });
        }
    };

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

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

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

            $scope.registryConfig.currentConfig.serverAddress = result.serverAddress;
            $scope.registryConfig.currentConfig.username = result.username || '';
            $scope.registryConfig.currentConfig.email = result.email || '';
            $scope.registryConfig.currentConfig.password = result.password;
        });
    }

    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.pollSubscriptionStatus = function () {
        Client.getSubscription(function (error, result) {
            if (error && error.statusCode === 412) return; // not yet registered
            if (error) return console.error(error);
            if (!$scope.$parent) return; // user changed view. otherwise we get an error that $scope.$parent is null

            $scope.subscription = result;

            // also reload the subscription on the main controller
            $scope.$parent.updateSubscriptionStatus();

            $timeout($scope.pollSubscriptionStatus, 10 * 1000);
        });
    };

    $('#avatarFileInput').get(0).onchange = function (event) {
        var fr = new FileReader();
        fr.onload = function () {
            $scope.$apply(function () {
                var tmp = {
                    file: event.target.files[0],
                    data: fr.result,
                    url: null
                };

                $scope.avatarChange.availableAvatars.push(tmp);
                $scope.avatarChange.setPreviewAvatar(tmp);
            });
        };
        fr.readAsDataURL(event.target.files[0]);
    };

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

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

            $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 = {
                serverAddress: $scope.registryConfig.serverAddress,
                username: $scope.registryConfig.username || '',
                password: $scope.registryConfig.password,
                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();
            });
        }
    };

    $scope.cloudronNameChange = {
        busy: false,
        error: {},
        name: '',

        reset: function () {
            $scope.cloudronNameChange.busy = false;
            $scope.cloudronNameChange.error.name = null;
            $scope.cloudronNameChange.name = '';

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

        show: function () {
            $scope.cloudronNameChange.reset();
            $scope.cloudronNameChange.name = $scope.config.cloudronName;
            $('#cloudronNameChangeModal').modal('show');
        },

        submit: function () {
            $scope.cloudronNameChange.error.name = null;
            $scope.cloudronNameChange.busy = true;

            Client.changeCloudronName($scope.cloudronNameChange.name, function (error) {
                $scope.cloudronNameChange.busy = false;

                if (error) {
                    if (error.statusCode === 400) {
                        $scope.cloudronNameChange.error.name = 'Invalid name';
                        $scope.cloudronNameChange.name = '';
                        $('#inputCloudronName').focus();
                        $scope.cloudronNameChangeForm.password.$setPristine();
                    } else {
                        console.error('Unable to change name.', error);
                        return;
                    }
                }

                $scope.cloudronNameChange.reset();
                $('#cloudronNameChangeModal').modal('hide');

                Client.refreshConfig();
            });
        }
    };

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

        $scope.update.checkStatus();

        getSubscription();
    });

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

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