/*
 * Copyright 2018 Scytl Secure Electronic Voting SA
 *
 * All rights reserved
 *
 * See our extended copyright notice in *file 'Copyright.txt' which is part of this source code package
 */
/* global require */

angular.module('app', [
    'lodash',
    'routes',
    'ngMaterial',
    'ngPromiseExtras',
    'settler',
    'partials',
    'gettext',
    'ngFileUpload',

    //  'menu',

    // filters
    'filters',

    // directives
    'svSidebar',
    'ovToolbar',
    'ovFolderInputDirective',
    'app.errors.dict',
    'datatableData',
    'ui.bootstrap.collapse',
    'tabBar',


    //services
    'app.sessionService',
    'endpoints',
    'databaseService',
    'app.dialogs',
    'app.progressbar',
    'i18n',
    'generateAdminBoardCert',
    'jobqueue',
    'statusBox',
    'ballotprinter',
    'toastCustom',
    'dialogsCustom',
    'boardActivation',
    'votingCardSet',
    'entitiesCounterService',
    'configElectionConstants',
    'activeFilters',

    // controllers
    'splash',
    'home-manage',
    'election-event-list',
    'administration-board-list',
    'election-event-manage',
    'ballots',
    'ballot-boxes',
    'voting-cards',
    'electoral-authorities',
    'members',
    'reconstructMembers'

])

.config(function($compileProvider, $provide) {
    'use strict';
    // $compileProvider.debugInfoEnabled(false);
    $provide.constant('$MD_THEME_CSS', '');
})

.run(function($rootScope, $state, databaseService, sessionService, i18n, gettextCatalog, $mdDialog, $mdToast, toastCustom, $http, endpoints) {

    'use strict';

    // safe apply

    $rootScope.safeApply = function(fn) {
        var phase = this.$root.$$phase;
        if (phase === '$apply' || phase === '$digest') {
            if (fn && (typeof(fn) === 'function')) {
                fn();
            }
        } else {
            this.$apply(fn);
        }
    };

    // ----------------------------------------------------------------------------------
    // language management

    $rootScope.switchLanguage = function(lang) {

        $rootScope.lang = lang.code;

        $rootScope.langAttr = $rootScope.transformLanguageCode(lang.code, true);

        gettextCatalog.setCurrentLanguage(lang.code);
        if (lang.code !== 'xx') { // 'xx' is the default (pseudo english) base lang
            //gettextCatalog.loadRemote('assets/lang/' + lang.code + '.json');
            var langUrl = endpoints.host + endpoints.languages + lang.code;
            gettextCatalog.loadRemote(langUrl);
        }
    };

    var setLanguages = function(defaultLanguage, languages) {
        $rootScope.i18n = {
            languages: languages,
            lang: {
                code: defaultLanguage,
            }
        };
    };
    $rootScope.transformLanguageCode = function(code, countryFormat) {
        // specify countryFormat to true if you want to add the country code. e.g. 'en-US'
        // don't if you just need the lang code. e.g. 'en'
        try {
            var langCode;
            if (countryFormat) {
                langCode = code.replace('_', '-');
            } else {
                langCode = code.split('_')[0];
            }
            return langCode;
        } catch(e) {
            return '';
        }
    };

    //-----------------------------------------------------------------------------------
    // user config

    $rootScope.getConfig = function() {
        $http.get(endpoints.host + endpoints.sdmConfig)
            .success(function(data) {
                setLanguages(data.config.i18n.default, data.config.i18n.languages);
                $rootScope.switchLanguage($rootScope.i18n.lang);

                sessionService.setGeneratePreVotingOutputsEnabled(data.config.generatePreVotingOutputsEnabled);
                sessionService.setGeneratePostVotingOutputsEnabled(data.config.generatePostVotingOutputsEnabled);
                sessionService.setVcGenerationPreparationEnabled(data.config.vcGenerationPreparationEnabled);
                sessionService.setVcPrecomputationEnabled(data.config.vcPrecomputationEnabled);
                sessionService.setVcComputationEnabled(data.config.vcComputationEnabled);
                sessionService.setVcDownloadEnabled(data.config.vcDownloadEnabled);
                sessionService.setDownloadParticipationEnabled(data.config.downloadParticipationEnabled);
                sessionService.setImportExportEnabled(data.config.importExportEnabled);
                sessionService.setTallyingEnabled(data.config.tallyingEnabled);

                // we go to the default page once the promise is a success
                // this is to prevent view blinking
                $state.go('election-event-list');
            });
    };

    // ----------------------------------------------------------------------------------
    // (spring-)batch summary success and error callbacks

    $rootScope.batchErrorSummary = function(batchType, aliases) {

        var title;
        switch (batchType) {
            case 'votingcardsets':
                title = gettextCatalog.getString('Some Voting Cards have not been generated successfully. Please contact support.');
                break;
            case 'decryption':
                title = gettextCatalog.getString('Some Ballot Boxes have not been decrypted successfully. Please contact support.');
                break;
            default:
                title = gettextCatalog.getString('Some errors were encountered during the process. Please contact support.') + ' (' + batchType + ')';;
        }
        $mdDialog.show(
            $mdDialog.customAlert({
                locals: {
                    title: title,
                    content: aliases.join(', ')
                }
            })
        );
    };

    $rootScope.batchSuccessSummary = function(batchType, count) {

        var msg;
        switch (batchType) {
            case 'votingcardsets':
                msg = gettextCatalog.getString('Voting Cards generated!');
                break;
            case 'decryption':
                msg = gettextCatalog.getString('Ballot boxes decrypted!');
                break;
            default:
                msg = 'unknown entities processed'; // shouldn't happen
        }
        $mdToast.show(
            toastCustom.topCenter(msg, 'success')
            // disable success counts for now
            // toastCustom.topCenter(msg)
            // toastCustom.topCenter('' + count + ' ' + msg)
        );
    };

    // ----------------------------------------------------------------------------------
    // startup

    if (typeof require !== 'undefined') {

        // if running in node webkit, spawn the local server

        var spawn = require('child_process').spawn;
        var process = require('process');
        var server = '/sdm/sdm-ws-rest.jar';

        var homedir = process.env.HOME || process.env.USERPROFILE;
        homedir = homedir.replace(/\\/g, '/');
        var app = homedir + server;
        var be = spawn('java', ['-jar', app]);

        be.stdout.pipe(process.stdout);
        console.log('Spawned ' + app + ' pid: ' + be.pid);

        // be shutdown

        var killProcess = function(callback) {
            console.log('Closing application...');
            be.kill();
            callback();
            return true;
        };

        var databaseClose = function(callback) {
            console.log('Closing database...');
            databaseService.close(function() {
                callback();
            });
            return true;
        };

        var shutdown = function(callback) {
            databaseClose(function() {
                killProcess(function() {
                    callback();
                });
            });
        };

        // install shutdown on window close

        var gui = require('nw.gui');
        var win = gui.Window.get();
        win.on('close', function() {
            var obj = this;
            obj.hide();
            shutdown(function() {
                obj.close(true);
            });
        });

        // install shutdown on sigint

        process.on('SIGINT', shutdown);

        // check cmd line args

        var i, argv = gui.App.argv;

        if (argv && argv.length) {

            for (i = 0; i < argv.length; i++) {
                switch (argv[i]) {
                    case '--expireAB':
                        sessionService.setKeyExpiration('ab', argv[i + 1]);
                        break;
                    case '--expireEA':
                        sessionService.setKeyExpiration('eb', argv[i + 1]);
                        break;
                }
            }
        }

    }

    function formatDate(date) {
        function pad(num, size) {
            var s = "000000000" + num;
            return s.substr(s.length - size);
        }
        return pad(date.getUTCHours(),2) + ':' +
            pad(date.getUTCMinutes(),2) + ':' +
            pad(date.getUTCSeconds(),2);
            // don't really need that precision:
            // + ':' +
            // pad(date.getUTCMilliseconds(), 3);
    }


    // var fs = require('fs');
    // var logfile = 'C:\\Users\\shaider\\AppData\\Roaming\\Skype\\My Skype Received Files\\sdmprogress.txt';
    // var os = fs.createWriteStream(logfile, {
    //         'flags': 'w'
    //     });
    // os.write(formatDate(new Date()) + ' log started\n');
    // os.end();


    $rootScope.log = function(data) {

        var ts = formatDate(new Date());
        var txt = ts + ';' + data;

        // console.log(txt);

        // var os = fs.createWriteStream(logfile, {
        //     'flags': 'a'
        // });
        // os.write(txt + '\n');
        // os.end();

    };

    $rootScope.isSync = function() {
        return sessionService.isSync();
    };
});
