angular.module('app').controller('StrategyConfigListCtrl', function ($scope) {
    $scope.settings = [];

    function print(data) {
        var processedData = processSettings(data);

        loadToArray($scope.settings, processedData);
        $scope.settings.forEach(function (item, index) {
            var thisCategoryDiffs = 0;
            item.settings.forEach(function (singleSettignItem) {
                if (!singleSettignItem.match) {
                    thisCategoryDiffs++;
                }
            });
            $scope.settings[index].diffs = thisCategoryDiffs;
            $scope.settings[index].opened = (thisCategoryDiffs > 0);
        });
    }

    function expandAll() {
        setOpenedToAll(true);
    }

    function collapseAll() {
        setOpenedToAll(false);
    }

    function setOpenedToAll(opened) {
        $scope.settings.forEach(function (item, index) {
            $scope.settings[index].opened = opened;
        });
    }

    function isDifferent(str, compareStrs) {
        let foundCompareStrs = compareStrs.filter((compareStr) => {
            return compareStr.index == str.index && compareStr.value == str.value;
        });
        return foundCompareStrs.length == 0;
    }

    function generateBacktestOnAdditionalMarketHtml(str, compareStrs, followedIndex = true) {
        let isAdditionalBacktestString = str.value.split(":")[0].indexOf("Additional backtest") != -1;
        let html = "";
        let foundCompareStrs = compareStrs.filter((compareStr) => {
            return (followedIndex && compareStr.index == str.index) || (!followedIndex && compareStr.value == str.value);
        });
        html = "<span class='notmatch'>" + str.value + "</span>";
        if (foundCompareStrs.length > 0) {
            let foundCompareStr = foundCompareStrs[0];
            let strings = str.value.split(",");
            let foundCompareStrings = foundCompareStr.value.split(",");
            let title = str.value.split(":")[0];
            let compareTitle = foundCompareStr.value.split(":")[0];
            
            if (title == compareTitle) {
                strings = strings.map((string) => {
                    if (foundCompareStrings.includes(string)) {
                        return string;
                    }
                    let subStrings = string.split(":");
                    if (subStrings.length > 2) {
                        return subStrings[0] + ":<span class='notmatch'>" + string.replace(subStrings[0] + ":", "") + "</span>";
                    }
                    return "<span class='notmatch'>" + string + "</span>";
                });
                html = strings.join(",");
            }
        }
        if (followedIndex) {
            console.log(html);
        }
        return "<div" + (isAdditionalBacktestString ? " style='margin-bottom:15px'" : "") + ">" + html + "</div>";
    }

    function processDifferences(key, checkStrs, compareStrs) {
        checkStrs.map((item) => {
            if (isDifferent(item, compareStrs)) {
                switch (key) {
                    case "Backtests on additional markets":
                    case "Custom filters":
                    case "Automatic filters":
                    case "Higher backtest precision":
                        item.html = generateBacktestOnAdditionalMarketHtml(item, compareStrs, key == "Backtests on additional markets");
                        break;
                    default:
                        item.html = "<span class='notmatch'>" + item.value + "</span>";
                }
            } else {
                item.html = item.value;
            }
            return item;
        });
        return checkStrs;
    }

    function requiredSort(key) {
        switch (key) {
            case "CrossChecks":
                return true;
            default:
                return false;
        }
    }

    function getCrossChecksSequence(key) {
        switch (key) {
            case "What If simulations":
                return 1;
            case "Monte Carlo trades manipulation":
                return 2;
            case "Higher backtest precision":
                return 3;
            case "Backtests on additional markets":
                return 4;
            case "Monte Carlo retest methods":
                return 5;
            case "Sequential Optimization":
                return 6;
            case "Opt. Profile / Sys. Param. Permutation":
                return 7;
            case "Walk-Forward Optimization":
                return 8;
            case "Walk-Forward Matrix":
                return 9;
            default:
                return 999;
        }
    }

    function processSettings(settings) {
        return settings.map(function(setting) {
            var modifiedSetting = setting;
            
            if (requiredSort(modifiedSetting.key)) {
                modifiedSetting.settings.sort((a, b) => {
                    return getCrossChecksSequence(a.key) - getCrossChecksSequence(b.key);
                });
            }
            
            modifiedSetting.settings = modifiedSetting.settings.map(function(setting2, index) {
                setting2.value_strs = setting2.value_str.split("<br><br>").filter(function(item) { 
                    return item; 
                }).map(function(item, index) {
                    return {value: item, index: index};
                });
                
                setting2.value_tasks = setting2.value_task.split("<br><br>").filter(function(item) { 
                    return item; 
                }).map(function(item, index) {
                    return {value: item, index: index};
                });

                setting2.value_strs = processDifferences(setting2.key, setting2.value_strs, setting2.value_tasks);
                setting2.value_tasks = processDifferences(setting2.key, setting2.value_tasks, setting2.value_strs);

                setting2.index = index;
                return setting2;
            });
            
            return modifiedSetting;
        });
    };

    // Watch for when instance becomes available
    $scope.$watch('instance', function(newValue) {
        if (newValue) {
            newValue.print = print;
            newValue.expandAll = expandAll;
            newValue.collapseAll = collapseAll;
        }
    });
});
