'use strict';

/* global $, angular, TASK_TYPES */

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

    $scope.ready = false;
    $scope.config = Client.getConfig();
    $scope.user = Client.getUserInfo();
    $scope.domains = [];

    $scope.pageItemCount = [
        { name: $translate.instant('main.pagination.perPageSelector', { n: 20 }), value: 20 },
        { name: $translate.instant('main.pagination.perPageSelector', { n: 50 }), value: 50 },
        { name: $translate.instant('main.pagination.perPageSelector', { n: 100 }), value: 100 }
    ];

    $scope.activityTypes = [
        { name: 'Bounce', value: 'bounce' },
        { name: 'Deferred', value: 'deferred' },
        { name: 'Delivered', value: 'delivered' },
        { name: 'Denied', value: 'denied' },
        { name: 'Queued', value: 'queued' },
        { name: 'Received', value: 'received' },
    ];

    $scope.activity = {
        busy: true,
        eventLogs: [],
        activeEventLog: null,
        currentPage: 1,
        perPage: 20,
        pageItems: $scope.pageItemCount[0],
        selectedTypes: [],
        search: '',

        refresh: function () {
            $scope.activity.busy = true;

            var types = $scope.activity.selectedTypes.map(function (a) { return a.value; }).join(',');

            Client.getMailEventLogs($scope.activity.search, types, $scope.activity.currentPage, $scope.activity.pageItems.value, function (error, result) {
                if (error) return console.error('Failed to fetch mail eventlogs.', error);

                $scope.activity.busy = false;

                $scope.activity.eventLogs = result;
            });
        },

        showNextPage: function () {
            $scope.activity.currentPage++;
            $scope.activity.refresh();
        },

        showPrevPage: function () {
            if ($scope.activity.currentPage > 1) $scope.activity.currentPage--;
            else $scope.activity.currentPage = 1;
            $scope.activity.refresh();
        },

        showEventLogDetails: function (eventLog) {
            if ($scope.activity.activeEventLog === eventLog) $scope.activity.activeEventLog = null;
            else $scope.activity.activeEventLog = eventLog;
        },

        updateFilter: function (fresh) {
            if (fresh) $scope.activity.currentPage = 1;
            $scope.activity.refresh();
        }
    };

    // this is required because we need to rewrite the MAIL_SERVER_NAME env var
    $scope.reconfigureEmailApps = function () {
        var installedApps = Client.getInstalledApps();
        for (var i = 0; i < installedApps.length; i++) {
            if (!installedApps[i].manifest.addons.email) continue;

            Client.repairApp(installedApps[i].id, { }, function (error) {
                if (error) console.error(error);
            });
        }
    };

    $scope.mailLocation = {
        busy: false,
        error: null,
        currentLocation: { domain: null, subdomain: '' },
        domain: null,
        subdomain: '',
        taskId: null,
        percent: 0,
        message: '',
        errorMessage: '',
        reconfigure: false,

        refresh: function () {
            Client.getMailLocation(function (error, location) {
                if (error) return console.error('Failed to get max email location', error);

                $scope.mailLocation.currentLocation.subdomain = location.subdomain;
                $scope.mailLocation.currentLocation.domain = $scope.domains.find(function (d) { return location.domain === d.domain; });

                Client.getLatestTaskByType(TASK_TYPES.TASK_CHANGE_MAIL_LOCATION, function (error, task) {
                    if (error) return console.error(error);
                    if (!task) return;

                    $scope.mailLocation.taskId = task.id;
                    $scope.mailLocation.reconfigure = task.active; // if task is active when this view reloaded, reconfigure email apps when task done
                    $scope.mailLocation.updateStatus();
                });
            });
        },

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

            $scope.mailLocation.domain = $scope.mailLocation.currentLocation.domain;
            $scope.mailLocation.subdomain = $scope.mailLocation.currentLocation.subdomain;

            $scope.mailLocationForm.$setUntouched();
            $scope.mailLocationForm.$setPristine();

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

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

                if (!data.active) {
                    $scope.mailLocation.taskId = null;
                    $scope.mailLocation.busy = false;
                    $scope.mailLocation.message = '';
                    $scope.mailLocation.percent = 0;
                    $scope.mailLocation.errorMessage = data.success ? '' : data.error.message;

                    if ($scope.mailLocation.reconfigure) $scope.reconfigureEmailApps();

                    return;
                }

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

                window.setTimeout($scope.mailLocation.updateStatus, 1000);
            });
        },

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

            Client.setMailLocation($scope.mailLocation.subdomain, $scope.mailLocation.domain.domain, function (error, result) {
                if (error) {
                    $scope.mailLocation.busy = false;
                    $scope.mailLocation.error = error;
                    return;
                }

                // update UI immediately
                $scope.mailLocation.currentLocation = { subdomain: $scope.mailLocation.subdomain, domain: $scope.mailLocation.domain };

                $scope.mailLocation.taskId = result.taskId;
                $scope.mailLocation.reconfigure = true; // reconfigure email apps when task done
                $scope.mailLocation.updateStatus();

                Client.refreshConfig(); // update config.mailFqdn

                $('#mailLocationModal').modal('hide');
            });
        }
    };

    $scope.maxEmailSize = {
        busy: false,
        error: null,
        size: 0,
        currentSize: 0,

        refresh: function () {
            Client.getMaxEmailSize(function (error, size) {
                if (error) return console.error('Failed to get max email size', error);

                $scope.maxEmailSize.currentSize = size;
            });
        },

        show: function() {
            $scope.maxEmailSize.busy = false;
            $scope.maxEmailSize.error = null;
            $scope.maxEmailSize.size = $scope.maxEmailSize.currentSize;

            $scope.maxEmailSizeChangeForm.$setUntouched();
            $scope.maxEmailSizeChangeForm.$setPristine();

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

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

            Client.setMaxEmailSize($scope.maxEmailSize.size, function (error) {
                $scope.maxEmailSize.busy = false;

                if (error) return console.error(error);

                $scope.maxEmailSize.currentSize = $scope.maxEmailSize.size;

                $('#maxEmailSizeChangeModal').modal('hide');
            });

        }
    };

    $scope.solrConfig = {
        busy: false,
        error: {},
        currentConfig: null, // null means not loaded yet
        enabled: false,
        running: false,
        enoughMemory: false,

        refresh: function () {
            Client.getService('mail', function (error, result) {
                if (error) return console.log('Error getting status of mail conatiner', error);

                $scope.solrConfig.enoughMemory = result.config.memoryLimit > (1024*1024*1024*2);
                $scope.solrConfig.running = result.healthcheck && result.healthcheck.solr.status;

                Client.getSolrConfig(function (error, config) {
                    if (error) return console.error('Failed to get solr config', error);

                    $scope.solrConfig.currentConfig = config;
                });
            });
        },

        show: function() {
            $scope.solrConfig.busy = false;
            $scope.solrConfig.error = null;
            $scope.solrConfig.enabled = $scope.solrConfig.currentConfig.enabled;

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

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

            Client.setSolrConfig($scope.solrConfig.enabled, function (error) {
                if (error) return console.error(error);

                $timeout(function () {
                    $scope.solrConfig.busy = false;
                    // FIXME: these values are fake. but cannot get current status from mail server since it might be restarting
                    $scope.solrConfig.currentConfig.enabled = $scope.solrConfig.enabled;
                    $scope.solrConfig.running = $scope.solrConfig.enabled;

                    $timeout(function () { $scope.solrConfig.refresh(); }, 20000); // get real values after 20 seconds

                    $('#solrConfigModal').modal('hide');
                }, 5000);
            });
        }
    };

    $scope.spamConfig = {
        busy: false,
        error: {},
        acl: { whitelist: [], blacklist: [] },
        customConfig: '',

        config: '',
        blacklist: '', // currently, we don't support whitelist because it requires user to understand a bit more of what he is doing

        refresh: function () {
            Client.getSpamCustomConfig(function (error, config) {
                if (error) return console.error('Failed to get custom spam config', error);

                $scope.spamConfig.customConfig = config;
            });

            Client.getSpamAcl(function (error, acl) {
                if (error) return console.error('Failed to get spam acl', error);

                $scope.spamConfig.acl = acl;
            });
        },

        show: function() {
            $scope.spamConfig.busy = false;
            $scope.spamConfig.error = {};

            $scope.spamConfig.blacklist = $scope.spamConfig.acl.blacklist.join('\n');
            $scope.spamConfig.config = $scope.spamConfig.customConfig;

            $scope.spamConfigChangeForm.$setUntouched();
            $scope.spamConfigChangeForm.$setPristine();

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

        submit: function () {
            $scope.spamConfig.busy = true;
            $scope.spamConfig.error = {};

            var blacklist = $scope.spamConfig.blacklist.split('\n').filter(function (l) { return l !== ''; });

            Client.setSpamAcl({ blacklist: blacklist, whitelist: [] }, function (error) {
                if (error) {
                    $scope.spamConfig.busy = false;
                    $scope.spamConfig.error.blacklist = error.message;
                    $scope.spamConfigChangeForm.blacklist.$setPristine();
                    return;
                }

                Client.setSpamCustomConfig($scope.spamConfig.config, function (error) {
                    if (error) {
                        $scope.spamConfig.busy = false;
                        $scope.spamConfig.error.config = error.message;
                        $scope.spamConfigChangeForm.config.$setPristine();
                        return;
                    }

                    $scope.spamConfig.busy = false;

                    $scope.spamConfig.refresh();

                    $('#spamConfigChangeModal').modal('hide');
                });
            });
        }
    },

    $scope.testEmail = {
        busy: false,
        error: {},

        mailTo: '',

        domain: null,

        clearForm: function () {
            $scope.testEmail.mailTo = '';
        },

        show: function (domain) {
            $scope.testEmail.error = {};
            $scope.testEmail.busy = false;

            $scope.testEmail.domain = domain;
            $scope.testEmail.mailTo = $scope.user.email;

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

        submit: function () {
            $scope.testEmail.error = {};
            $scope.testEmail.busy = true;

            Client.sendTestMail($scope.testEmail.domain.domain, $scope.testEmail.mailTo, function (error) {
                $scope.testEmail.busy = false;

                if (error) {
                    $scope.testEmail.error.generic = error.message;
                    console.error(error);
                    $('#inputTestMailTo').focus();
                    return;
                }

                $('#testEmailModal').modal('hide');
            });
        }
    };

    function refreshDomainStatuses() {
        $scope.domains.forEach(function (domain) {
            Client.getMailStatusForDomain(domain.domain, function (error, result) {
                if (error) return console.error('Failed to fetch mail status for domain', domain.domain, error);

                domain.status = result;

                domain.statusOk = Object.keys(result).every(function (k) {
                    if (k === 'dns') return Object.keys(result.dns).every(function (k) { return result.dns[k].status; });

                    if (!('status' in result[k])) return true; // if status is not present, the test was not run

                    return result[k].status;
                });
            });

            Client.getMailConfigForDomain(domain.domain, function (error, mailConfig) {
                if (error) return console.error('Failed to fetch mail config for domain', domain.domain, error);

                domain.inbound = mailConfig.enabled;
                domain.outbound = mailConfig.relay.provider !== 'noop';

                // do this even if no outbound since people forget to remove mailboxes
                Client.getMailboxCount(domain.domain, function (error, count) {
                    if (error) return console.error('Failed to fetch mailboxes for domain', domain.domain, error);

                    domain.mailboxCount = count;

                    Client.getMailUsage(domain.domain, function (error, usage) {
                        if (error) return console.error('Failed to fetch usage for domain', domain.domain, error);

                        domain.usage = 0;
                        Object.keys(usage).forEach(function (m) { domain.usage += usage[m].size; });
                    });
                });
            });
        });
    }

    Client.onReady(function () {
        Client.getDomains(function (error, domains) {
            if (error) return console.error('Unable to get domain listing.', error);

            $scope.domains = domains;
            $scope.ready = true;

            if ($scope.user.role === 'owner') $scope.activity.refresh();

            $scope.mailLocation.refresh();
            $scope.maxEmailSize.refresh();
            $scope.spamConfig.refresh();
            $scope.solrConfig.refresh();

            refreshDomainStatuses();
        });
    });

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

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