'use strict';

/* global angular */
/* global $ */

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

    $scope.config = Client.getConfig();
    $scope.servicesReady = false;
    $scope.services = [];
    $scope.hasRedisServices = false;
    $scope.redisServicesExpanded = false;
    $scope.memory = null;

    function refresh(serviceName, callback) {
        callback = callback || function () {};

        Client.getService(serviceName, function (error, result) {
            if (error) return console.log('Error getting status of ' + serviceName + ':' + error.message);

            var service = $scope.services.find(function (s) { return s.name === serviceName; });
            if (!service) $scope.services.find(function (s) { return s.name === serviceName; });

            service.status = result.status;
            service.config = result.config;
            service.memoryUsed = result.memoryUsed;
            service.memoryPercent = result.memoryPercent;

            callback(null, service);
        });
    }

    $scope.restartService = function (serviceName) {
        function waitForActive(serviceName) {
            refresh(serviceName, function (error, result) {
                if (result.status === 'active') return;

                setTimeout(function () { waitForActive(serviceName); }, 3000);
            });
        }

        $scope.services.find(function (s) { return s.name === serviceName; }).status = 'starting';

        Client.restartService(serviceName, function (error) {
            if (error && error.statusCode === 404) {
                Client.rebuildService(serviceName, function (error) {
                    if (error) return Client.error(error);

                    // show "busy" indicator for 3 seconds to show some ui activity
                    setTimeout(function () { waitForActive(serviceName); }, 3000);
                });

                return;
            }
            if (error) return Client.error(error);

            // show "busy" indicator for 3 seconds to show some ui activity
            setTimeout(function () { waitForActive(serviceName); }, 3000);
        });
    };

    $scope.serviceConfigure = {
        error: null,
        busy: false,
        service: null,

        // form model
        memoryLimit: 0,
        memoryTicks: [],

        // sftp only
        requireAdmin: true,

        show: function (service) {
            $scope.serviceConfigure.reset();

            $scope.serviceConfigure.service = service;
            $scope.serviceConfigure.memoryLimit = service.config.memoryLimit;

            // TODO improve those
            $scope.serviceConfigure.memoryTicks = [];

            // create ticks starting from manifest memory limit. the memory limit here is currently split into ram+swap (and thus *2 below)
            // TODO: the *2 will overallocate since 4GB is max swap that cloudron itself allocates
            $scope.serviceConfigure.memoryTicks = [];
            var npow2 = Math.pow(2, Math.ceil(Math.log($scope.memory.memory)/Math.log(2)));
            for (var i = 256; i <= (npow2*2/1024/1024); i *= 2) {
                $scope.serviceConfigure.memoryTicks.push(i * 1024 * 1024);
            }

            if (service.name === 'sftp') $scope.serviceConfigure.requireAdmin = !!service.config.requireAdmin;

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

        submit: function (memoryLimit) {
            $scope.serviceConfigure.busy = true;
            $scope.serviceConfigure.error = null;

            var data = { memoryLimit: memoryLimit };
            if ($scope.serviceConfigure.service.name === 'sftp') data.requireAdmin = $scope.serviceConfigure.requireAdmin;

            Client.configureService($scope.serviceConfigure.service.name, data, function (error) {
                $scope.serviceConfigure.busy = false;
                if (error) {
                    $scope.serviceConfigure.error = error.message;
                    return;
                }

                refresh($scope.serviceConfigure.service.name);

                $('#serviceConfigureModal').modal('hide');
                $scope.serviceConfigure.reset();
            });
        },

        resetToDefaults: function () {
            $scope.serviceConfigure.memoryLimit = 536870912; // 512MB default
        },

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

            $scope.serviceConfigure.memoryLimit = 0;
            $scope.serviceConfigure.memoryTicks = [];

            $scope.serviceConfigureForm.$setPristine();
            $scope.serviceConfigureForm.$setUntouched();
        }
    };

    $scope.refreshAll = function (callback) {
        Client.getServices(function (error, result) {
            if (error) return Client.error(error);

            $scope.services = result.map(function (name) {
                var displayName = name;
                var isRedis = false;

                if (name.indexOf('redis') === 0) {
                    isRedis = true;
                    var app = Client.getCachedAppSync(name.slice('redis:'.length));
                    if (app) {
                        displayName = 'Redis (' + (app.label || app.fqdn) + ')';
                    } else {
                        displayName = 'Redis (unknown app)';
                    }
                }

                return {
                    name: name,
                    displayName: displayName,
                    isRedis: isRedis
                };
            });
            $scope.hasRedisServices = !!$scope.services.find(function (service) {  return service.isRedis; });

            // just kick off the status fetching
            $scope.services.forEach(function (s) { refresh(s.name); });

            if (callback) return callback();
        });
    };

    Client.onReady(function () {
        Client.memory(function (error, memory) {
            if (error) console.error(error);

            $scope.memory = memory;

            $scope.refreshAll(function () {
                $scope.servicesReady = true;
            });
        });
    });

}]);
