angular.module('app').service('ConditionsGridService', function (BackendService, AppService, SQConstants, ColumnSettingsService) {

    this.getValueTypes = function () {
        return instance.valueTypes;
    }

    this.getConditionDetails = function (conditionsObj, rowIndex, colIndex, columns) {
        var conditionDetails = {
            numericValue: 10,
            direction: instance.directions.both + "",
            sampleType: instance.sampleTypes.full + "",
            plType: instance.plTypes.money + "",
        }

        if (columns.length > 0) {
            conditionDetails.valueType = instance.valueTypes.column;
            conditionDetails.column = columns[0].class;
            conditionDetails.columnType = columns[0].columnType;
            conditionDetails.columnName = columns[0].name;
            conditionDetails.format = columns[0].type;
            conditionDetails.category = columns[0].category;
        } else {
            conditionDetails.valueType = instance.valueTypes.numeric;
        }

        var conditionObj = getChildElements(conditionsObj, "Condition")[rowIndex];
        if (!conditionObj) {
            return conditionDetails;
        }

        var objName = colIndex == 1 ? "Left-Side" : "Right-Side";
        var sideObj = getChildElements(conditionObj, objName)[0];
        if (!sideObj) {
            return conditionDetails;
        }

        var valueType = correctAttrValue(sideObj.attributes["valueType"]);
        var valueObj = null;

        if (valueType == instance.valueTypes.numeric) {
            valueObj = getChildElements(sideObj, 'Numeric-Value')[0];
            if (valueObj) {
                conditionDetails.valueType = valueType,
                    conditionDetails.numericValue = correctAttrValue(valueObj.attributes["value"]);
                conditionDetails.column = "Number";
                conditionDetails.columnName = "Number";
            }

            conditionDetails.format = instance.getNumberFormat(sideObj);

        } else if (valueType == instance.valueTypes.column) {
            valueObj = getChildElements(sideObj, 'Column-Value')[0];
            if (valueObj) {
                conditionDetails.valueType = valueType,
                    conditionDetails.column = correctAttrValue(valueObj.attributes["column"]);

                var column = getItem(columns, 'class', conditionDetails.column);
                conditionDetails.category = column ? column.category : "";
                conditionDetails.format = column ? column.type : "";
                conditionDetails.columnType = column ? column.columnType : "";
                conditionDetails.columnName = column ? column.name : "";

                conditionDetails.resultType = getAttrStringValue(valueObj, "resultType", instance.resultTypes.main);

                conditionDetails.direction = correctAttrValue(valueObj.attributes["direction"]);
                conditionDetails.sampleType = correctAttrValue(valueObj.attributes["sampleType"]);
                conditionDetails.plType = correctAttrValue(valueObj.attributes["plType"]);

                conditionDetails.confidenceLevel = getAttrIntValue(valueObj, "confidenceLevel", 50);
                conditionDetails.market = getAttrIntValue(valueObj, "market", 1);
                conditionDetails.subresult = getAttrIntValue(valueObj, "subresult", instance.wfSubresultsList[0].value);

                var pct = getAttrIntValue(valueObj, "pctRatio", 0);
                conditionDetails.pctRatio = pct > 0;
                conditionDetails.pctRatioValue = conditionDetails.pctRatio ? pct : 60;
            }
        }


        conditionDetails.valueObj = valueObj;

        return conditionDetails;
    }

    this.removeCondition = function (conditionsObj, rowIndex, callback) {
        var conditionObj = getChildElements(conditionsObj, "Condition")[rowIndex];
        if (!conditionObj) {
            return;
        }

        conditionsObj.removeChild(conditionObj);

        if (callback) {
            callback();
        }
    }

    this.addCondition = function (conditionsObj, use, columnClass, comparator, value, columns, sampleType, resultType = "") {
        var conditionObj = createChild(conditionsObj, 'Condition', AppService.xmlDoc, true);
        conditionObj.setAttribute('use', use);

        var leftSideObj = createChild(conditionObj, 'Left-Side', AppService.xmlDoc);
        leftSideObj.setAttribute("valueType", instance.valueTypes.column);

        var columnValueObj = createChild(leftSideObj, 'Column-Value', AppService.xmlDoc);

        var column = getItem(columns, 'class', columnClass);
        columnValueObj.setAttribute("column", column ? column.class : '');
        columnValueObj.setAttribute("format", column ? column.type : '');

        //special WF stlpce
        var columnItem = getItem(instance.columns, 'class', columnClass);
        if (columnItem && columnItem.columnType == instance.columnTypes.wfSpecial.value) {
            columnValueObj.setAttribute("resultType", 'WalkForwardOptimization');
            columnValueObj.setAttribute("subresult", instance.columnTypes.wfSpecial.value);
        } else {
            columnValueObj.setAttribute("resultType", resultType ? resultType : instance.resultTypes.main);
            columnValueObj.setAttribute("subresult", instance.wfSubresultsList[0].value);
        }

        columnValueObj.setAttribute("direction", instance.directions.both);
        columnValueObj.setAttribute("sampleType", sampleType);
        columnValueObj.setAttribute("plType", instance.plTypes.money);

        columnValueObj.setAttribute("confidenceLevel", 50);
        columnValueObj.setAttribute("market", 1);

        var comparatorObj = createChild(conditionObj, 'Comparator', AppService.xmlDoc);
        comparatorObj.setAttribute('value', comparator);

        var rightSideObj = createChild(conditionObj, 'Right-Side', AppService.xmlDoc);
        rightSideObj.setAttribute("valueType", instance.valueTypes.numeric);

        var numericValueObj = createChild(rightSideObj, 'Numeric-Value', AppService.xmlDoc);
        numericValueObj.setAttribute("value", value);
    }

    this.updateCondition = function (conditionsObj, rowIndex, colIndex, data, callback) {
        var xmlDoc = AppService.xmlDoc;
        var conditionObj = getChildElements(conditionsObj, "Condition")[rowIndex];
        if (!conditionObj) {
            conditionObj = xmlDoc.createElement("Condition");
            conditionObj.setAttribute('use', false);
            conditionObj.appendChild(xmlDoc.createElement("Left-Side"));
            conditionObj.appendChild(xmlDoc.createElement("Comparator"));
            conditionObj.appendChild(xmlDoc.createElement("Right-Side"));

            conditionsObj.appendChild(conditionObj);
        }

        if (colIndex == 0) {
            conditionObj.setAttribute('use', data);

        } else if (colIndex == 1 || colIndex == 3) {
            var objName = colIndex == 1 ? "Left-Side" : "Right-Side";
            var sideObj = getChildElements(conditionObj, objName)[0];

            sideObj.setAttribute("valueType", data.valueType);
            removeAllChildren(sideObj);

            var valueObj;
            if (data.valueType == instance.valueTypes.numeric) {
                valueObj = xmlDoc.createElement("Numeric-Value");
                valueObj.setAttribute("value", data.numericValue);

            } else {
                valueObj = xmlDoc.createElement('Column-Value');
                valueObj.setAttribute("column", data.column);
                valueObj.setAttribute("columnType", data.columnType);
                valueObj.setAttribute("format", data.format);
                valueObj.setAttribute("resultType", data.resultType);
                valueObj.setAttribute("direction", data.direction);
                valueObj.setAttribute("sampleType", data.sampleType);
                valueObj.setAttribute("plType", data.plType);

                valueObj.setAttribute("confidenceLevel", data.confidenceLevel);
                valueObj.setAttribute("market", data.market);

                valueObj.setAttribute("subresult", data.subresult);
                if (data.subresult == instance.columnTypes.wfStability.value || data.subresult == instance.columnTypes.wfScore.value) {
                    valueObj.setAttribute("format", 'Decimal2Pct');
                }

                valueObj.setAttribute("pctRatio", data.pctRatio ? data.pctRatioValue : 0);
            }

            sideObj.appendChild(valueObj);

            data.valueObj = valueObj;

        } else if (colIndex == 2) {
            var comparatorObj = getChildElements(conditionObj, "Comparator")[0];
            comparatorObj.setAttribute('value', data);
        }

        if (callback) {
            callback();
        }
    }

    this.updateRecentConditions = function (recentConditions, callback) {

        recentConditions.sort(function (x, y) {
            if (x.weight < y.weight) {
                return -1;
            }
            if (x.weight > y.weight) {
                return 1;
            }
            return 0;
        }).reverse();

        recentConditions = recentConditions.slice(0, 20);
        // AppService.saveSetting("recentlyUsedConditionsColumns", JSON.stringify([]), function () { });

        AppService.saveSetting("recentlyUsedConditionsColumns", JSON.stringify(recentConditions), function () { });

        callback();

        /* BackendService.sendRequest('dbviews/updateRecentColumns', { lastUsedCols : recentCols }, callback); */
    }

    this.getConditionValue = function (sideObj) {
        if (sideObj && sideObj.attributes["valueType"]) {
            var valueType = correctAttrValue(sideObj.attributes["valueType"]);
            if (valueType == instance.valueTypes.numeric) {
                var valueObj = getChildElements(sideObj, "Numeric-Value")[0];
                if (valueObj) {
                    var value = correctAttrValue(valueObj.attributes["value"]);

                    var format = instance.getNumberFormat(sideObj);
                    if (format) {
                        return instance.formatNumber(value, format);
                    }
                    return value;
                } else {
                    return null;
                }
            } else {
                checkColumnValueCorrectness(sideObj);

                return getColumnText(sideObj);
            }
        }

        return null;
    }

    function checkColumnValueCorrectness(sideObj) {
        var valueObj = getChildElements(sideObj, 'Column-Value')[0];

        var resultType = correctAttrValue(valueObj.attributes["resultType"]);
        var resultTypeItem = getItem(instance.resultTypesList, "value", resultType);
        if (!resultTypeItem) {
            valueObj.setAttribute("resultType", instance.resultTypes.main);
        }

        var plType = correctAttrValue(valueObj.attributes["plType"]);
        if (!plType && plType != instance.plTypes.money && plType != instance.plTypes.percent && plType != instance.plTypes.pips) {
            valueObj.setAttribute("plType", instance.plTypes.money);
        }
    }

    this.getNumberFormat = function (sideObj) {
        var conditionObj = findParentElement(sideObj, 'Condition');
        if (conditionObj) {
            var columnValueObj = conditionObj.find('Column-Value')[0];
            if (columnValueObj) {
                return getAttrValue(columnValueObj, 'format');
            }
        }

        return null;
    }

    this.formatNumber = function (value, format) {
        if (value < 0) {
            switch (format) {
                case instance.columnValueTypes.Decimal2: return parseInt(value * 100 - 0.1) / 100;
                case instance.columnValueTypes.Decimal4:
                case instance.columnValueTypes.Decimal5: return value;
                case instance.columnValueTypes.Decimal2Pct: return (parseInt(value * 100 - 0.1) / 100) + ' %';
                case instance.columnValueTypes.Decimal2Pips: return (parseInt(value * 100 - 0.1) / 100) + ' pips';
                case instance.columnValueTypes.Decimal2PL: return (parseInt(value * 100 - 0.1) / 100); //'$ ' + (parseInt(value * 100 + 0.1) / 100); Decimal2PL should print $,%,pips based on plType
                case instance.columnValueTypes.Integer: return parseInt(value);
                default: return value;
            }
        } else {
            switch (format) {
                case instance.columnValueTypes.Decimal2: return parseInt(value * 100 + 0.1) / 100;
                case instance.columnValueTypes.Decimal4:
                case instance.columnValueTypes.Decimal5: return value;
                case instance.columnValueTypes.Decimal2Pct: return (parseInt(value * 100 + 0.1) / 100) + ' %';
                case instance.columnValueTypes.Decimal2Pips: return (parseInt(value * 100 + 0.1) / 100) + ' pips';
                case instance.columnValueTypes.Decimal2PL: return (parseInt(value * 100 + 0.1) / 100); //'$ ' + (parseInt(value * 100 + 0.1) / 100); Decimal2PL should print $,%,pips based on plType
                case instance.columnValueTypes.Integer: return parseInt(value);
                default: return value;
            }
        }
    }

    this.unformatNumber = function (value) {
        return value.replace(' %', '').replace(' pips', '').replace('$ ', '');
    }

    function getColumnText(sideObj) {
        var valueObj = getChildElements(sideObj, 'Column-Value')[0];

        var valueText = "";
        var value = correctAttrValue(valueObj.attributes["value"]);
        if (value) {
            var format = correctAttrValue(valueObj.attributes["format"]);
            valueText = " (" + instance.formatNumber(value, format) + ")";
        }

        valueObj.setAttribute("class", getAttrValue(valueObj, "column"));

        var columnText = ColumnSettingsService.printColumnTitle(valueObj);
        var pctRatio = getAttrIntValue(valueObj, "pctRatio", 0);
        if (pctRatio > 0) {
            columnText = pctRatio + '% of ' + columnText;
        }

        return columnText + valueText;
    }

    this.printCondition = function (conditionObj) {
        var leftSideObj = getChildElement(conditionObj, "Left-Side");
        var comparatorObj = getChildElement(conditionObj, "Comparator");
        var rightSideObj = getChildElement(conditionObj, "Right-Side");

        var value1 = instance.getConditionValue(leftSideObj);
        var comparator = comparatorObj ? (correctAttrValue(comparatorObj.attributes['value']) || '') : '';
        var value2 = instance.getConditionValue(rightSideObj);

        return value1 + " " + comparator + " " + value2;
    }

    this.saveConditions = function (data, callOnSuccess) {
        BackendService.sendRequest('main/saveConditions', data, callOnSuccess, 'POST');
    }

    this.loadConditions = function (data, callOnSuccess) {
        BackendService.sendRequest('main/loadConditions', data, callOnSuccess);
    }

    var instance = this;

    this.directions = SQConstants.getConstants().directions;
    this.sampleTypes = SQConstants.getConstants().sampleTypes;
    this.plTypes = SQConstants.getConstants().plTypes;
    this.columnValueTypes = SQConstants.getConstants().columnValueTypes;

    this.columnTypes = SQConstants.getConstants().databankColumnTypes;
    this.columns = SQConstants.getColumnsByType([instance.columnTypes.general, instance.columnTypes.wfSpecial]);

    this.valueTypes = {
        numeric: 'numeric',
        column: 'column'
    }

    this.resultTypes = SQConstants.getConstants().resultTypes;
    this.resultTypesList = SQConstants.getConstants().resultTypesList;
    this.wfSubresultsList = SQConstants.getConstants().wfSubresultsList;

});