angular.module('app').controller('sqUtilsCtrl', function ($scope, $rootScope, $timeout, sqPlugin, AppService, BackendService, SQConstants, SQEvents, L, $injector) {
    $scope.broker = SQConstants.getConstants().broker;
    $scope.isBrazilianEdition = SQConstants.getConstants().isBrazilianEdition;

    function init(){
        if($scope.isMainApp){
            loadPerformanceSettings();
            if(!isQuantDataManager()) loadAWExamples();

            window.callAction = function(name, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10){
                if($rootScope[name]){
                    return $rootScope[name](p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
                }
                else {
                    $rootScope.showError(L.tsq("Calling unknown action '%s'", [name]));
                }
            }
        }
        else {
            window.regenerate = regenerate;
            
            window.getPerformanceSettings = function(callback){
                return window.parent.getPerformanceSettings(callback);
            }
        }
    }

    //- Common functions -------------------------------------------------------------------------

    $rootScope.openLink = function (link) {
        AppService.openBrowser(link);
    }

    $rootScope.regenerate = regenerate;

    function regenerate() {
        AppService.regenerate().then(function (result) {
            if (result.success) {
                console.log("regenerated");
                if(!isQuantDataManager()) showResults(false);
                location.reload();
            } else {
                var msg = L.tsq("Regeneration failed.") + " <br>";
                if (result.data.error) {
                    msg += result.data.error
                }
                $rootScope.showError(msg);
            }
        });
    }

    var lastErrorMessage = null;
    $rootScope.showError = function(message) {
        console.error(message);

        if(lastErrorMessage==message) {
            return;
        } else {
            lastErrorMessage = message;

            $timeout( function(){
                lastErrorMessage = null;
            }, 5000, false);
        }

        sqNotices.addNotice('error', L.tsq(message));
    }    
    
    var lastSuccessMessage = null;
    $rootScope.showSuccess = function(message){
        console.log(message);

        if(lastSuccessMessage==message) {
            return;
        } else {
            lastSuccessMessage = message;

            $timeout( function(){
                lastSuccessMessage = null;
            }, 5000, false);
        }
        
        sqNotices.addNotice('success', L.tsq(message));
    }
    
    $rootScope.showNotice = function(message){
        console.log(message);
        sqNotices.addNotice('notice', L.tsq(message));
    }
    
    $rootScope.applyConfigToTask = function(config, taskName, callback) {
        var xmlDoc = AppService.xmlDoc;

        if(!config) {
            $rootScope.showError(L.tsq("Cannot apply config to task '%s'. Invalid source task.", [taskName]));
            return;
        }

        var inputXmlObj = xmlToObject(config);
        var newSettingsObj = inputXmlObj.find('Settings')[0];
        if(!newSettingsObj){
            $rootScope.showError(L.tsq("Cannot apply config to task '%s'. Source task doesn't contain any settings", [taskName]));
            return;
        }

        let elProject = AppService.getProjectConfig();
        let elTasks = getChildElement(elProject, "Tasks");
        let taskElems = getChildElements(elTasks, "Task");

        let targetTaskConfig = null;
        let targetTaskXMLFile = null;
        let targetTaskType = null;
        for(let i=0; i<taskElems.length; i++){
            let elTask = taskElems[i];
            let curTaskName = getAttrStringValue(elTask, "name", null);
            let curTaskXMLFile = getAttrStringValue(elTask, "taskXMLFile", null);

            if(curTaskName === taskName){
                targetTaskType = getAttrStringValue(elTask, "type", null);
                targetTaskConfig = SQConstants.getTaskConfig(AppService.getProject(), curTaskXMLFile, true);
                targetTaskXMLFile = curTaskXMLFile;
                break;
            }
        }

        if(!targetTaskConfig) {
            $rootScope.showError(L.tsq("Cannot apply config to task '%s'. Cannot find task with this name", [taskName]));
            return;
        }

        var existingSettingElems = getNonTextChildren(targetTaskConfig);
        var newSettingElems = getNonTextChildren(newSettingsObj);
        var settingPlugins = sqPlugin.getPlugins('SettingsTab');

        var ccSettingsExists = false;
        var atmSettingsExists = false;
        let hasTask = false;
        let hasRelatedTask = false;

        let alreadyReplaced = [];

        for(var i=0; i<newSettingElems.length; i++){
            var newSettingElem = newSettingElems[i];

            if(newSettingElem.nodeName=="CrossChecks") {
                ccSettingsExists = true;
            }
            else if(newSettingElem.nodeName=="ATMs") {
                atmSettingsExists = true;
            }

            var settingPlugin = getItem(settingPlugins, 'configElemName', newSettingElem.nodeName);
            if(!settingPlugin){
                console.debug("Cannot find setting plugin with configElemName '" + newSettingElem.nodeName + "'");
                continue;
            }

            if(settingPlugin.task.split(',').indexOf(targetTaskType) >= 0){
                hasTask = true;
            }

            if(settingPlugin.relatedTask && settingPlugin.relatedTask.split(',').indexOf(targetTaskType) >= 0){
                hasRelatedTask = true;
            }
            
            if(hasTask || hasRelatedTask){
                var existingSetting = getItem(existingSettingElems, 'nodeName', newSettingElem.nodeName);
                if(!existingSetting){
                    existingSetting = createChild(targetTaskConfig, newSettingElem.nodeName, AppService.xmlDoc);
                }

                if(!alreadyReplaced.includes(newSettingElem.nodeName)) {
                    targetTaskConfig.replaceChild(newSettingElem, existingSetting);

                    alreadyReplaced.push(newSettingElem.nodeName)
                }
            }
        }

        //console.log("Replaced settings", alreadyReplaced);

        if(!ccSettingsExists) {
            var crossChecksObj = getItem(existingSettingElems, 'nodeName', 'CrossChecks');
            if(crossChecksObj) {
                crossChecksObj.setAttribute("use", false);
            }
        }
        
        if(!atmSettingsExists) {
            var atmsObj = getItem(existingSettingElems, 'nodeName', 'ATMs');
            if(atmsObj) {
                atmsObj.setAttribute("enable", false);
            }
        }

        console.log("Config loaded to task '"+taskName+"'");

        if(AppService.getTask().taskXMLFile === targetTaskXMLFile){
            let newXML = xmlToString(targetTaskConfig);
    
            AppService.taskXMLConfig = xmlToObject(newXML);
            AppService.taskXMLDoc = getXMLDoc(newXML);
        }

        var complexitiesService = $injector.get('ComplexitiesService');
        complexitiesService.loadComplexities();

        SQEvents.notifyListeners(SQEvents.get('SETTINGS_TAB_RELOAD'), 'all');
        SQEvents.notifyListeners(SQEvents.get('RELOAD_DATABANKS'));

        $timeout(function(){
            AppService.updateTaskXML(targetTaskXMLFile, targetTaskConfig).then(function(){

                if(callback) callback();
            });
        }, 1000, false);
    }

    //- Main app functions -------------------------------------------------------------------------
        
    $rootScope.showErrorModal = function(title, message, displayTextarea, isHtmlContent) {
        if(!$scope.isMainApp){
            return window.parent.callAction("showErrorModal", title, message, displayTextarea, isHtmlContent);
        }

        $scope.errorDialog.title = title;
        $scope.errorDialog.message = message;
        $scope.errorDialog.displayTextarea = displayTextarea;
        $scope.errorDialog.isHtmlContent = isHtmlContent;

        try { $scope.$digest(); } catch (err) {}
        showPopup('#errorDialog');
    }

    $rootScope.showConfirm = function(title, message, callback, showYesNo, closeCallback, okButtonTitle, deleteConfirm){
        if(!$scope.isMainApp){
            return window.parent.callAction("showConfirm", title, message, callback, showYesNo, closeCallback, okButtonTitle, deleteConfirm);
        }

        $scope.confirmDialog.title = title;
        $scope.confirmDialog.message = message;
        $scope.confirmDialog.callback = callback;
        $scope.confirmDialog.yesNo = showYesNo;
        $scope.confirmDialog.closeCallback = closeCallback;
        $scope.confirmDialog.okButtonTitle = okButtonTitle;
        $scope.confirmDialog.deleteConfirm = deleteConfirm;

        try { $scope.$digest(); } catch (err) {}
        
        $timeout(function(){
            showPopup("#confirmDialog");
        }, 0, false);
    }

    
    $rootScope.showOptionsDialog = function(title, message, callback, options, hideClose){
        if(!$scope.isMainApp){
            return window.parent.callAction("showOptionsDialog", title, message, callback, options, hideClose);
        }

        $scope.optionsDialog.title = title;
        $scope.optionsDialog.message = message;
        $scope.optionsDialog.callback = callback;
        $scope.optionsDialog.options = options;
        $scope.optionsDialog.hideClose = hideClose;

        try { $scope.$digest(); } catch (err) {}
        
        $timeout(function(){
            showPopup("#optionsDialog");
        }, 0, false);
    }
    
    $rootScope.showFilePicker = function(title, actionType, showFiles, multiselection, currentDir, extension, fileName, onSelect) {
        if(!$scope.isMainApp){
            return window.parent.callAction("showFilePicker", title, actionType, showFiles, multiselection, currentDir, extension, fileName, onSelect);
        }

        $scope.filePicker.title = title;
        $scope.filePicker.actionType = actionType;
        $scope.filePicker.currentDir = currentDir;
        $scope.filePicker.showFiles = showFiles;
        $scope.filePicker.multiselection = multiselection;
        $scope.filePicker.extension = extension;
        $scope.filePicker.fileName = fileName;

        if(onSelect) {
            $scope.filePicker.onSelect = onSelect;
        }
        
        $scope.filePicker.showDialog();
        
        try { $scope.$digest(); } catch (err) {}

        return $scope.filePicker;
    }

    $rootScope.setProgressInfo = function(title, info, percent, callback, forceShowing){
        if(!$scope.isMainApp){
            return window.parent.callAction("setProgressInfo", title, info, percent, callback, forceShowing);
        }

        $scope.progress.title = title || '';
        $scope.progress.info = info || '';
        $scope.progress.percent = percent;
        $scope.progress.callback = callback;

        try { $scope.$digest(); } catch (err) {}

        if(forceShowing) showProgressPopup('#progressModal');
    }
    
    $rootScope.updateProgress = function(percent, info, title){
        if(!$scope.isMainApp){
            return window.parent.callAction("updateProgress", percent, info, title);
        }

        $scope.progress.percent = percent;
        $scope.progress.info = info || $scope.progress.info;
        $scope.progress.title = title || $scope.progress.title;

        try { $scope.$digest(); } catch (err) {}

        if(percent == 'infinite' || (percent >= 0 && percent < 100)){
            if(!isPopupOpen('#progressModal')){
                showProgressPopup('#progressModal');
            }
        }
        else if(percent == 100) {
            setTimeout(function(){
                $rootScope.closeProgressModal();
                $scope.progress.percent = 0;
            }, 500);
        } 
    }
    
    function showProgressPopup(id){
        var modalOptions = {
            'backdrop': 'static',
            'keyboard': false,
            'show': true,
        };

        $(id).modal(modalOptions);
    }
    
    $rootScope.closeProgressModal = function(){
        if(!$scope.isMainApp){
            return window.parent.callAction("closeProgressModal");
        }

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

    $rootScope.updateSavingProgress = function(percent, info, cancelCallback, showExitButton){
        if(!$scope.isMainApp){
            return window.parent.callAction("updateSavingProgress", percent, info, cancelCallback, showExitButton);
        }

        $scope.savingProgress.percent = percent;
        $scope.savingProgress.info = info || $scope.savingProgress.info;
        $scope.savingProgress.cancelCallback = cancelCallback || $scope.savingProgress.cancelCallback;
        $scope.savingProgress.showExitButton = showExitButton;

        try { $scope.$digest(); } catch (err) {}

        if(percent == 'infinite' || (percent >= 0 && percent < 100)){
            if(!isPopupOpen('#saveStrategiesProgressModal')){
                showProgressPopup('#saveStrategiesProgressModal');
            }
        }
        else if(percent == 100) {
            setTimeout(function(){
                $('#saveStrategiesProgressModal').modal('hide');
                $scope.savingProgress.percent = 0;
            }, 500);
        } 
    }

    //if callback is defined, chooseFile will be called on backend. Then, providing the target path, the file will be saved via callback function
    $rootScope.saveFile = function(title, extension, pathKey, fileName, fileContent, callback){
        if(!$scope.isMainApp){
            return window.parent.callAction("saveFile", title, extension, pathKey, fileName, fileContent, callback);
        }

        if(window.electron) {
            const dialogConfig = {
                title: title,
                filters: [],
                defaultPath: fileName,
                properties: ['createDirectory ']
            };

            if(extension) {
                if (typeof extension === 'string') {
                    dialogConfig.filters.push({ 
                        name: 'Custom File Type', 
                        extensions: extension.split(',')
                    });
                } else if (Array.isArray(extension)) {
                    extension.forEach(function(ext) {
                        dialogConfig.filters.push({ 
                            name: ext.description, 
                            extensions: ext.name.split(',')
                        });
                    });
                } else if ( extension.description && extension.name) {
                    dialogConfig.filters.push({ 
                        name: extension.description, 
                        extensions: extension.name.split(',')
                    });
                }
            }

            console.log("Opening file chooser: ", title, extension, pathKey, fileName, callback);

            electron.openDialog('showSaveDialog', dialogConfig).then(result => {
                console.log("File selected", result)

                if (!result.filePath) {
                    return;
                }

                if(callback) {
                    callback(result.filePath);
                } else {
                    AppService.createFile(result.filePath, fileContent, function(){
                        $rootScope.showSuccess(L.tsq("File saved"));
                    });
                }
            });

        } else {
            var hasMoreExtensions = extension && ("" + extension.constructor).indexOf("Array") >= 0;
            if(hasMoreExtensions){
                $scope.saveFile.extensions = angular.copy(extension);
                $scope.saveFile.extension = $scope.saveFile.extensions[0];
            }
            else {
                $scope.saveFile.extensions = [];
                $scope.saveFile.extension = extension || {};
            }
            
            $scope.saveFile.title = title;
            $scope.saveFile.pathKey = pathKey;
            $scope.saveFile.fileName = fileName || '';
            
            $scope.saveFile.callback = function(path) {
                if(callback) {
                    callback(path);
                    hidePopup("#saveFileDialog");
                    return;
                }

                AppService.createFile(path, fileContent, function(){
                    hidePopup("#saveFileDialog");
                    $rootScope.showSuccess(L.tsq("File saved"));
                });
            }

            try { $scope.$digest(); } catch (err) {}
            showPopup('#saveFileDialog');
        }
    } 

    $rootScope.resolveResources = function(xmlConfig, resourcesXML, actionType, callback, filePath){
        if(!$scope.isMainApp){
            window.parent.callAction("onResolveResources", xmlConfig, resourcesXML, actionType, callback, filePath);
        }
        else {
            $rootScope.onResolveResources(xmlConfig, resourcesXML, actionType, callback, filePath);
        }
    }

    //-------------------------------------------------------------------------------------------------------
    
    $rootScope.checkFileExists = function(filePath, callback) {
        BackendService.sendRequest('/main/checkFileExists', {filePath: filePath}, callback);
    }    

    //-------------------------------------------------------------------------------------------------------
    
    $rootScope.showBenchmark = function(afterStart) {
        if(afterStart) {
            if(SQConstants.getConstants().benchmarkTimePerTick==0) {
                $scope.benchmark.show(true);        
            }
        } else {
            $scope.benchmark.show();        
        }
    }

    //-------------------------------------------------------------------------------------------------------

    $scope.setAutoSyncToAllDatabanks = function(){
        $scope.disableAutoSyncButton = true;

        BackendService.getPromise('/main/setAutoSyncToAllDatabanks', { syncType : $scope.performance.databankSyncInterval }).then(function(result) {
            $scope.disableAutoSyncButton = false;
            
            if(result.data.success){
                $rootScope.showSuccess(result.data.success);
                SQEvents.notifyListeners(SQEvents.get("CHANGE_AUTOSYNC_GLOBAL"), $scope.performance.databankSyncInterval);
            }
            else {
                $rootScope.showError(result.data.error);
            }
        });
    }

    //-------------------------------------------------------------------------------------------------------

    $scope.onSavePerformanceSettings = function(){
        BackendService.sendRequest('/main/setPerformanceSettings', $scope.performance, function(result) {
            window.parent.isSoundAllowed = !$scope.performance.soundsoff;

            SQConstants.getSettings()["databankSyncType"] = $scope.performance.databankSyncInterval;
            
            hidePopup('#performanceDialog');
            $rootScope.showSuccess(result.success);
        }, 'POST', false, true);
    }

    //-------------------------------------------------------------------------------------------------------

    function loadPerformanceSettings() {
        BackendService.sendRequest("main/getPerformanceSettings", null, function(data) {
            $scope.performance = data;    
            $scope.performance.soundsoff = SQConstants.getConstants().global.soundsoff;
            window.isSoundAllowed = !$scope.performance.soundsoff;

            $scope.performance.showControlOrders = SQConstants.getConstants().global.showControlOrders;

            $scope.performance.headerCustomText = SQConstants.getConstants().global.headerCustomText;
            $scope.performance.footerCustomText = SQConstants.getConstants().global.footerCustomText;

            $scope.performance.computePipsMetrics = SQConstants.getConstants().global.computePipsMetrics;
            $scope.performance.computePctsMetrics = SQConstants.getConstants().global.computePctsMetrics;
            $scope.performance.computeSeparateMetrics = SQConstants.getConstants().global.computeSeparateMetrics;

            $scope.performance.defaultResultToDisplay = SQConstants.getConstants().global.defaultResultToDisplay;

            $scope.performance.autoUpdate = SQConstants.getConstants().global.autoUpdate;
            $scope.performance.fileBasedDatabanks = $scope.performance.databankSyncInterval == SQConstants.getConstants().databankSyncTypes.immediately;

            $rootScope.performanceSettings = angular.copy($scope.performance);

            if(!window.performanceSettingsCallbacks) window.performanceSettingsCallbacks = [];

            for(let i=0; i<window.performanceSettingsCallbacks.length; i++){
                window.performanceSettingsCallbacks[i]($rootScope.performanceSettings);
            }

            window.performanceSettingsCallbacks.length = 0;
            
            window.getPerformanceSettings = function(callback){
                return callback($rootScope.performanceSettings);
            }
        });
    }

    function loadAWExamples() {
        let awEditor = $injector.get("AlgoWizardService");
        if(awEditor) {
            awEditor.loadExamples(function(data) {
                loadToArray($scope.awExamples, data);

                $timeout(function(){
                    $("#awExamplesDialog").on("shown.bs.modal", function() {
                        $("#awExamplesDialog .aw-examples-wrapper").slick({
                            infinite: false,
                            slidesToShow: 3,
                            slidesToScroll: 1,
                            arrows: true,
                            variableWidth: false,
                        });
                    });
                }, 0, false);
            });
        }
    }
    
    $scope.loadExampleFile = function(fileName) {
        console.log("AW editor loading example file ... " + fileName);

        let awEditor = $injector.get("AlgoWizardService");
        if(awEditor) {
            awEditor.loadExample({fileName: fileName}, function(data) {
                awEditor.editorAction("loadStrategy", {
                    strategyXML: data.sourceCode,
                    lastSettings: data.lastSettingsXML,
                    lastSettingsXML: data.lastSettingsXML,
                    fileName: fileName
                });
            });
        }
    }

    //-------------------------------------------------------------------------------------------------------

    $scope.onSaveRemoteAccessSettings = function(){
        BackendService.sendRequest('/main/setremoteaccess', $scope.remoteAccess, function(){
            $rootScope.showSuccess(L.tsq("Remote Access settings saved."));
            
            hidePopup('#remoteAccessDialog');
        });
    }

    $scope.onSaveSMTPSettings = function() {
        BackendService.sendRequest("main/saveSMTPSettings", $scope.smtp, function(data) {
            $rootScope.showSuccess(L.tsq("SMTP settings saved."));

            hidePopup('#smtpDialog');
        });
    }

    $scope.testSMTP = function() {
        if(!$scope.smtp.recipient.includes('@')) {
            $scope.smtp.testResult = L.tsq("Please specify your email address.");

            return;
        }

        BackendService.sendRequest("main/testSMTP", $scope.smtp, function(data) {
            $scope.smtp.testResult = data.result;

            try { $scope.$digest(); } catch (err) {}
        });
    }

    $scope.getCleanupIntervalName = function(value){
        var interval = getItem($scope.cleanupIntervals, "value", value);
        return interval ? L.tsq(interval.name) : "N/A";
    }
	
	$scope.onCloseNewVersionDialog = function(){
        hidePopup('#newVersionDialog');
    }	

	$scope.onInstallNewVersion = function(){
        hidePopup('#newVersionDialog');
		exitapp(true);
    }		

    $rootScope.dataTrialPopup = function(){
        showPopup('#dataTrialPopup');
    }

    $rootScope.showRemoteAccessSettings = function(){
        if(!$scope.isMainApp){
            return window.parent.callAction("showRemoteAccessSettings");
        }

        AppService.getRemoteAccessSettings(function(settings){
            $scope.remoteAccess.allow = settings.allow;
            $scope.remoteAccess.requirePassword = settings.requirePassword;
            $scope.remoteAccess.secureConnection = settings.secureConnection;

            $scope.remoteAccess.password = '';

            showPopup('#remoteAccessDialog');
        });
    }

    $rootScope.showSMTPSettings = function() {
        if(!$scope.isMainApp){
            return window.parent.callAction("showSMTPSettings");
        }

        $scope.smtp.testResult = null;
        $scope.smtp.sendTestEmail = false;

        BackendService.sendRequest("main/getSMTPSettings", null, function(data) {
            $scope.smtp.server = data.server;
            $scope.smtp.port = data.port;
            $scope.smtp.username = data.username;
            $scope.smtp.password = data.password;
            $scope.smtp.ssl = data.ssl;
            $scope.smtp.emailFrom = data.emailFrom;

            try { $scope.$digest(); } catch (err) {}

            showPopup('#smtpDialog');
        });
    }

    $rootScope.showCSVXLSXExportDialog = function(fileName, pathName, callback){
        if(!$scope.isMainApp){
            return window.top.callAction("showCSVXLSXExportDialog", fileName, pathName, callback);
        }

        showPopup('#CSVXLSXExportDialogModal');	

        $scope.CSVXLSXExport.callback = function(asXLSX){
            if(!callback){
                $rootScope.showError("No callback function defined");
                return;
            }

            var extension = {
                name : asXLSX ? "xlsx" : "csv",
                description : asXLSX ? "XLSX files" : "CSV files"
            };

            $rootScope.saveFile(L.tsq("Select folder to export content"), extension, pathName, fileName, null, function(path){
                callback(path, $scope.CSVXLSXExport.useComma);
                hidePopup("#CSVXLSXExportDialogModal");
                hidePopup("#saveFileDialog");
            });
        };
    }

    $rootScope.showMoveDatabankDialog = function(callback){
        $scope.moveDatabankDialog.newPosition = 1;
        $scope.moveDatabankDialog.callback = callback;

        $scope.$evalAsync();
        showPopup('#moveDatabankDialog');	
    }
	
    $rootScope.checkUpdate = function() {
        if(!$scope.isMainApp){
            return window.parent.callAction("checkUpdate");
        }

        BackendService.sendRequest("main/checkupdate", null, function(data) {
            var newVer = data.newVersionExists;
			
			if (newVer===true){
			    showPopup('#newVersionDialog');	
			}else{
				showPopup('#noNewVersionDialog');	
			}
        });
    }

    $rootScope.formatDateTime = function(s) {   
        var day =  Math.floor(s / 86400);
        var hour =  Math.floor(s / 3600);
        var min =  Math.floor(s / 60);

        if (day > 0) {
            return L.tsq("%dd %dh %dm", [s / 86400, (s % 86400) / 3600, (s % 3600) / 60]);
		} else if (hour > 0) {
			return L.tsq("%dh %dm", [s / 3600, (s % 3600) / 60]);
		} else if (min > 0) {
			return L.tsq("%dm %ds", [(s % 3600) / 60, s % 60]);
		} else {
			return L.tsq("%ds", [s % 60]);
		}
    }

    $rootScope.showPopup = showPopup;

    $scope.openBrowser = AppService.openBrowser;
    
    $rootScope.about = function() {
        window.parent.broadcastEvent(SQEvents.get('OPEN_ABOUT_DIALOG'));
    }

    $rootScope.updateLicense = function() {
        window.parent.broadcastEvent(SQEvents.get('OPEN_ABOUT_DIALOG'), {update: true});
    }

    $rootScope.openlink = function(link) {
        BackendService.sendRequest('/main/openlink', {url: link});
    }    

    $rootScope.exitapp = function() {
        $rootScope.showConfirm(L.tsq("User Confirmation"), L.tsq("Are you sure you want to exit?"), exitapp); 
    }

    var exitapp = function(confirmed) {
        if(confirmed){
            BackendService.sendRequest('/main/exitapp', {}, function(){
                $rootScope.showSuccess(L.tsq("Terminating SQX..."));
                setTimeout(function(){ window.parent.location.reload(); }, 5000);
            });
        }
    }

    //- Initialization -------------------------------------------------------------------------

    var performanceSettingsLoaded = false;

    $scope.progress = {};
    $scope.savingProgress = {};
    $scope.confirmDialog = { title: 'x' };
    $scope.optionsDialog = { title: 'x', options: [], hideClose: false};
    $scope.errorDialog = { title: 'x' };

    $scope.linkURL = location.protocol + '//' + location.hostname + (location.port ? ':' + location.port : '');
    $scope.remoteAccess = {}
    
    $scope.filePicker = {
        title: '',
        currentDir: '',
        onSelect: function(){}
    } 

    $scope.saveFile = {
        extension : {}
    }
    
    $scope.popups = sqPlugin.getPopups();

    $scope.isMainApp = window.appConfig.product == "SQUANT" || (window.appConfig.product == "RESULTS" && window.parent.appConfig.product == "AlgoWizard") || window.appConfig.product == "QDM" || window.appConfig.product == "SQEDITOR";

    $scope.smtp = {
        server: null,
        port: 25,
        username: null,
        password: null,
        ssl: false,
        emailFrom: null,
        recipient: null,
        ports: [25, 465, 587, 2525],
        sendTestEmail: false,
        testResult: null
    }

    $scope.performanceOptions = SQConstants.getConstants().performance.options;
    $scope.cleanupIntervals = SQConstants.getConstants().memoryCleanupIntervals;
    $scope.gcTypes = SQConstants.getConstants().gcTypes;
    
	$scope.databankSyncOptions = {};
	try {
		var DatabankSyncService = $injector.get("DatabankSyncService");             //available in SQ only
		if(DatabankSyncService){
			$scope.databankSyncOptions = DatabankSyncService.getGlobalOptions();
		}
	} catch(err) {
		//ignoge
	}

    $scope.benchmark = {};

    $scope.performance = {
        soundsoff: false,
        advancedFileChooser: true,
		autoUpdate:true,
        headerCustomText: null,
        footerCustomText: null,
        computePipsMetrics: false,
        computePctsMetrics: false,
        computeSeparateMetrics: true,
        defaultResultToDisplay: 'portfolio'
    };
    
    $scope.awExamples = [];

    $scope.CSVXLSXExport = {
        useComma : SQConstants.getSettings()['CSVExportUseComma'] == "true"
    };

    $scope.moveDatabankDialog = {
        newPosition : 1
    };

    init();

});