angular.module("app").directive("sqDataBox", function ($rootScope, $state, SQEvents, SQConstants, UniqueIdGenerator, $timeout, $document, AppService, SkinService) {
    return {
        restrict: 'E',
        replace: false,
        scope: {
            disabled: '=',
            sqModel: '=',
            change: '&',
            engine: '=',
            addSpyBenchmark: '=?'
        },
        templateUrl: "../app/directives/sqDataBox/sqDataBox.html",
        controller: function ($scope, $element) {

            $scope.dropdownClicked = function (event) {
                event.stopPropagation();
                if (event.target.classList.contains("jqcloud-word")) {
                    $scope.filterTypeValue = -1;
                    $scope.sqModel = event.target.innerText;
                    $scope.addItemToRecentSymbols($scope.sqModel);
                    $scope.dropdownClose();
                }
            }

            $scope.dropdownClose = function () {
                $scope.dropdownOpened = false;
                $scope.filterText = "";
                $($element).find(".recent-cloud").jQCloud("destroy");
                $scope.selector.catchKeyEvents = false;
                $scope.$evalAsync();
            };

            $scope.redrawTagCloud = function () {
                try {
                    $($element).find(".recent-cloud").jQCloud("destroy");
                }
                catch (e) { }

                var cloudColours = ["#000000", "#444444", "#666666", "#888888", "#aaaaaa", "#cccccc", "#aaaaaa", "#bbbbbb", "#cccccc", "#dddddd"];
                var skin = SkinService.selectedSkin.name;
                if (skin == 'Dark skin') {
                    cloudColours = cloudColours.reverse();
                }

                let wordsForCloudAll = JSON.parse(JSON.stringify($scope.recentlyUsedSymbols));
                var wordsForCloud = [];
                let wordsForCloudAllSymbols = [];

                for (let i = 0; i < wordsForCloudAll.length; i++) {
                    if ($scope.filterTypeValue == -1 || (wordsForCloudAll[i].text in $scope.dataToCategoryMap && $scope.dataToCategoryMap[wordsForCloudAll[i].text] == $scope.filterTypeValue)) {
                        wordsForCloud.push(wordsForCloudAll[i]);
                        wordsForCloudAllSymbols.push(wordsForCloudAll[i].text);
                    }
                }

                for (let i = 0; i + wordsForCloud.length < 20; i++) {
                    if (i >= $scope.availableData.length) {
                        break;
                    }
                    if ($scope.filterTypeValue != -1 && $scope.filterTypeValue != $scope.availableData[i].dataType) {
                        continue;
                    }
                    if (wordsForCloudAllSymbols.indexOf($scope.availableData[i].symbol) >= 0) {
                        continue;
                    }
                    wordsForCloud.push({ text: $scope.availableData[i].symbol, weight: 1 });
                }

                wordsForCloud = wordsForCloud.filter(function (item) {
                    for (var i = 0; i < $scope.availableData.length; i++) {
                        if (item.text == $scope.availableData[i].symbol) {
                            return true;
                        }
                    }
                    return false;
                });

                wordsForCloud = wordsForCloud.slice(0, 20);

                $($element).find(".recent-cloud").jQCloud(wordsForCloud, {
                    autoResize: true,
                    steps: 5,
                    fontSize: {
                        from: 0.06,
                        to: 0.030
                    }
                });
            }

            $scope.dropdownOpen = function () {
                if($scope.disabled) return;
                $scope.dropdownOpened = true;
                $scope.filterText = "";
                $scope.selector.catchKeyEvents = true;
                $scope.$evalAsync();
                $scope.reloadSelector();

                $timeout(function () {
                    $scope.selector.markItemByValue($scope.sqModel, true);
                    $scope.redrawTagCloud();

                }, 0, false);
            }
        },
        link: function (scope, element, attrs) {

            function loadAvailableData(checkCurrentSymbol) {
                scope.availableData.length = 0;
                scope.dataTypesList = {};
                scope.dataToCategoryMap = {};

                var constants = SQConstants.getConstants();
                if (!constants.data) return;

                let currentSymbolFound = false;

                var allData = angular.copy(constants.data);
                if (scope.addSpyBenchmark){
                    allData.unshift({rows:100, show:true, dataType:1, symbol:'SPY_benchmark.D',
                    barType: 1,
                    broker: -1,
                    brokerName: "SQ default",
                    connection: "History",
                    source: 5,
                    sourceDataId: 0,
                    timeframe: "D1",
                    timezone: "Exchange",
                    uSymbol: "SPY_benchmark.D",
                    uSymbolName: "SPY (S&P 500)"                    
                    });
                }

                for (var i = 0; i < allData.length; i++) {
                    var data = allData[i];
                    if (data.rows > 0 && data.show) {

                        if(AppService.getTask().type == "Optimize") {
                            if((scope.engine=='Stockpicker' && !isBasketAlias(data.symbol)) || ((scope.engine!='Stockpicker' && scope.engine!='Single-asset cloud strategy' && isBasketAlias(data.symbol)))) { //baskets [[SP500]] only for stockpicker/single-asset cloud
                                continue;
                            }

                            if(scope.engine=='Single-asset cloud strategy' && (data.dataType != 1 && data.dataType != 5 && !isBasketAlias(data.symbol))) { //only stocks/etf/baskets
                                continue;
                            }
                        } else {
                            if((scope.engine=='Stockpicker' && !isBasketAlias(data.symbol)) || (scope.engine!='Stockpicker' && isBasketAlias(data.symbol))) { //baskets [[SP500]] only for stockpicker
                                continue;
                            }

                            if(scope.engine=='Single-asset cloud strategy' && (data.dataType != 1 && data.dataType != 5)) { //only stocks/etf
                                continue;
                            }
                        }

                        scope.availableData.push(data);
                        scope.dataToCategoryMap[data.symbol] = data.dataType;

                        if(data.symbol === scope.sqModel) {
                            currentSymbolFound = true;
                        }
                    }
                }

                scope.availableData.sort(function (a, b) {
                    if (a.symbol < b.symbol) {
                        return -1;
                    }
                    if (a.symbol > b.symbol) {
                        return 1;
                    }
                    return 0;
                });


                scope.availableData = scope.availableData.filter(item=>{
                    if((item.symbol.startsWith("[") && item.readyToUse) || !item.symbol.startsWith("[")){
                        return item;
                    }
                });

                for (var i = 0; i < constants.dataTypes.length; i++) {
                    scope.dataTypesList[constants.dataTypes[i].value] = constants.dataTypes[i].name;
                }

                regenerateFilterDataOptions();

                scope.reloadSelector();

                scope.selector.markItemByValue(scope.sqModel, true);

                if (SQConstants.getSettings().recentlyUsedSymbolsWeights != undefined) {
                    try {
                        scope.recentlyUsedSymbols = JSON.parse("" + SQConstants.getSettings().recentlyUsedSymbolsWeights);
                    } catch (exp) {
                        scope.recentlyUsedSymbols = [];
                    }
                }
                
                if(!currentSymbolFound && checkCurrentSymbol){
                    $timeout(function(){ scope.sqModel = scope.availableData[0].symbol;});
                }
            } 

            function regenerateFilterDataOptions() {
                let filterOptions = [];
                for (var i = 0; i < scope.availableData.length; i++) {
                    var currentType = scope.availableData[i].dataType;
                    if (filterOptions.indexOf(currentType) < 0) {
                        filterOptions.push(currentType);
                    }
                }

                filterOptions.sort(function (x, y) { return scope.dataTypesList[x] == "Forex" ? -1 : scope.dataTypesList[y] == "Forex" ? 1 : 0; });

                scope.filterTypeOptions = filterOptions;
            }

            scope.addItemToRecentSymbols = function (symbolName) {
                for (var i = 0; i < scope.recentlyUsedSymbols.length; i++) {
                    if (scope.recentlyUsedSymbols[i].text == symbolName) {
                        scope.recentlyUsedSymbols[i].weight++;
                        return;
                    }
                }
                scope.recentlyUsedSymbols.push({
                    text: symbolName,
                    weight: 2
                });

                AppService.saveSetting("recentlyUsedSymbolsWeights", JSON.stringify(scope.recentlyUsedSymbols), function () { });
            }

            scope.selectFilterType = function (dataType) {
                scope.filterTypeValue = dataType;
                scope.reloadSelector();
                scope.redrawTagCloud();
            }

            scope.shouldShowItem = function (dataItem) {
                if (scope.filterText != "" && dataItem.symbol.toLowerCase().indexOf(scope.filterText.toLowerCase()) < 0) {
                    return false;
                }
                if (scope.filterTypeValue == -1 || dataItem.dataType == scope.filterTypeValue) {
                    return true;
                }
                return false;
            }

            scope.reloadSelector = function () {

                let itemsForSelector = [];
                if (scope.filterTypeValue == -1 && scope.filterText == '') {
                    for (let i = 0; i < scope.availableData.length; i++) {
                        itemsForSelector.push({
                            name: scope.availableData[i].symbol=='SPY_benchmark.D'?'SPY benchmark':scope.availableData[i].symbol,
                            value: scope.availableData[i].symbol,
                            group: scope.dataTypesList[scope.availableData[i].dataType],
                        });
                    }
                }
                else {
                    for (let i = 0; i < scope.availableData.length; i++) {
                        if (!scope.shouldShowItem(scope.availableData[i])) {
                            continue;
                        }
                        itemsForSelector.push({
                            name: scope.availableData[i].symbol,
                            value: scope.availableData[i].symbol,
                            group: scope.dataTypesList[scope.availableData[i].dataType],
                        });
                    }
                }

                scope.selector.loadItems(itemsForSelector);
            }

            $document.bind("keyup", keyUpHandler);

            function keyUpHandler(event) {
                if (!scope.dropdownOpened) {
                    return;
                }

                /*                 if (event.key == "Enter") {
                                    let selectedItem = scope.selector.getSelectedItem();
                                    if (selectedItem) {
                                        scope.sqModel = selectedItem.value;
                                        scope.addItemToRecentSymbols(scope.sqModel);
                                        scope.dropdownClose();
                                    }
                                    return;
                                } */
                if (event.key.length == 1) {
                    scope.filterText += event.key;
                    scope.reloadSelector();
                    event.preventDefault();
                    scope.$evalAsync();
                    return;
                }
                if (event.key == "Backspace") {
                    scope.filterText = scope.filterText.slice(0, -1)
                    scope.reloadSelector();
                    event.preventDefault();
                    scope.$evalAsync();
                    return;
                }
            }

            $document.bind('click', documentClickHandler);

            function documentClickHandler() {
                scope.dropdownClose();
            }

            element.bind('click', elementClickHandler);

            function elementClickHandler(e) {
                e.stopPropagation();
            }

            function onEvent(event, data) {
                if (event == SQEvents.get('DATA_CHANGED')) {

                    //console.error("sqDatABox data changed", angular.copy(SQConstants.getConstants().data));
                    loadAvailableData();
                }
                else return;

                try { scope.$digest(); } catch (er) { }
            }
            scope.$on("$destroy", function () {
                destroySqModelWatch();
                destroyEngineWatch();

                SQEvents.removeListener(listenerId);
                UniqueIdGenerator.removeId(id);

                $document.unbind('keyup', keyUpHandler);
                $document.unbind('click', documentClickHandler);
                element.unbind('click', elementClickHandler);
            });

            var destroySqModelWatch = scope.$watch("sqModel", function (newValue) {
                if (valueFilled(newValue)) {
                    scope.selector.markItemByValue(scope.sqModel, true);
                }
            });

            var destroyEngineWatch = scope.$watch("engine", function (newValue) {
                if (initialized && valueFilled(newValue)) {
                   loadAvailableData(true);
                }
                initialized = true;
            });

            var id = UniqueIdGenerator.generateId();
            var listenerId = "SQDataInput-" + id;
            var initialized = false;

            scope.availableData = [];
            scope.dataToCategoryMap = {};
            scope.dataTypesList = {};
            scope.filterTypeOptions = [];
            scope.filterTypeValue = -1;
            scope.dropdownOpened = false;
            scope.recentlyUsedSymbols = [];
            scope.filterText = "";

            scope.selector = new sqSelector($(element).find(".data-selector"));

            scope.selector.onClickEvent = function (item) {
                if (!item) {
                    return;
                }
                scope.sqModel = item.value;
                scope.addItemToRecentSymbols(scope.sqModel);
                scope.dropdownClose();
            }

            loadAvailableData();

            SQEvents.addListener(listenerId, [
                SQEvents.get('DATA_CHANGED')
            ], onEvent);
        }
    };
});