// Copyright (c) 2000-2019 Ericsson Telecom AB Telecom AB                                                       //
// All rights reserved. This program and the accompanying materials are made available under the     //
// terms of the Eclipse Public License v2.0 which accompanies this distribution, and is available at //
// https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html                                                         //
///////////////////////////////////////////////////////////////////////////////////////////////////////
function RequestConsole_RequestEditor_ViewModel(p_model, p_parent) {
    "use strict";

    var v_model = p_model;
    var v_parent = p_parent;
    var dataSourceUtils = new DataSourceUtils();
    var v_desktopData;
    var v_binder;

    var v_help;
    var v_requests = [];
    var v_requestBuilder = new DSHelpToRequest_manual();
    v_requestBuilder.setRequest(v_requests);

    var v_this = this;

    ///////////////////// GENERAL FUNCTIONS /////////////////////

    this.init = function(p_callback) {
        function helpArrived(ok, help) {
            if (ok) {
                v_help = help;
                p_callback(true);
            } else {
                p_callback(false, "Error getting help");
            }
        }

        v_model.getDsRestAPI().getHelp(helpArrived);
    };

    this.setBinder = function(p_binder) {
        v_binder = p_binder;
    };

    this.setSetup = function(setup) {
        v_requests = setup.request.getData();
        v_requestBuilder.setRequest(v_requests);
    };
    
    this.modelChanged = function() {
        if (v_binder)
            v_binder.modelChanged();
    }

    ///////////////////// FUNCTIONS FOR VIEW VISUALIZATION /////////////////////

    this.getHelp = function(refresh, toSort, elementIcon) {
        function helpArrived(ok, p_help) {
            if (ok) {
                v_help = p_help;
                var help = new HelpTreeBuilder(mcopy(v_help)).getHelpTree(toSort);
                v_requestBuilder.setHelp(help);
                var jsTreeData = dataSourceUtils.convertHelpToTreeDataArray(help.sources, elementIcon);
                refresh(jsTreeData);
            } else {
                alert("Failed to get help");
                refresh([]);
            }
        }
        v_model.getDsRestAPI().getHelp(helpArrived);
    };

    this.getRawHelp = function() {
        return v_help;
    };

    this.getRequestTree = function(refresh) {
        var jsTreeData = dataSourceUtils.convertRequestToTreeDataArray(v_requests);
        refresh(jsTreeData);
    };

    this.getFilterAsTree = function(p_path) {
        var filter = v_requestBuilder.getFilterPart(p_path, []);
        var treeData = [];
        if (filter != undefined) {
            traverseFilter(filter, treeData);
        }
        return treeData;
    };

    function traverseFilter(filter, treeData, paramName) {
        var treeNode;
        var treeNodeText = "";
        if (paramName != undefined) {
            treeNodeText = paramName + ": ";
        }
        if (filter.dataValue != undefined) {
            treeNode = {"text": treeNodeText + filter.dataValue};
            treeData.push(treeNode);
        } else if (filter.request != undefined) {
            treeNode = {"text": treeNodeText + filter.request.element, "children": []};
            treeData.push(treeNode);
            if (filter.request.params != undefined && filter.request.params.length > 0) {
                for (var i = 0; i < filter.request.params.length; ++i) {
                    traverseFilter(filter.request.params[i].paramValue, treeNode.children, filter.request.params[i].paramName);
                }
            }
            if (filter.request.remapTo != undefined) {
                traverseFilter(filter.request.remapTo, treeNode.children, "remapTo");
            }
        }
    }

    this.findSelectionsAndFilters = function() {
        traverseRequest(v_requests, [], selectionOrFilterChanged);
    };

    function selectionOrFilterChanged(node, path) {
        if (node.getData)
            v_binder.selectionOrFilterChanged(path, node.getData.selection != undefined, node.getData.filter != undefined, node.getData.rangeFilter != undefined, node.getData.writableInfo != undefined, "getData");
        else if (node.setData)
            v_binder.selectionOrFilterChanged(path, node.setData.selection != undefined, node.setData.filter != undefined, node.setData.rangeFilter != undefined, node.setData.writableInfo != undefined, "setData");
    }

    function traverseRequest(list, path, processGetData) {
        for (var i = 0; i < list.length; ++i) {
            path.push(i);
            processGetData(list[i], path);
            if (list[i].getData && list[i].getData.children != undefined) {
                traverseRequest(list[i].getData.children, path, processGetData);
            } else if (list[i].setData && list[i].setData.children != undefined) {
                traverseRequest(list[i].setData.children, path, processGetData);
            }
            path.pop();
        }
    }

    this.selectionAdded = function(p_path) {
        var request = v_this.getRequestFromPath(p_path);
        if (request.getData.selection == undefined) {
            request.getData.selection = [0];
        }
        selectionOrFilterChanged(request, p_path);
        v_parent.setupChanged("Selection added");
    };

    this.setDesktopData = function(p_data) {
        v_desktopData = p_data;
    };

    this.getDesktopData = function() {
        return v_desktopData;
    };

    this.getRequestSchema = function() {
        return v_model.getRequestSchema();
    }

    ///////////////////// FUNCTIONS FOR REQUEST EDITING /////////////////////

    this.createRequest = function(p_helpPath, p_position, partialRefresh) {
        var request = v_requestBuilder.createRequest(p_helpPath, p_position);
        partialRefresh([p_position], dataSourceUtils.convertRequestToTreeDataArray([request])[0]);
        v_parent.setupChanged('Request added: "' + request.getData.element + '"');
    };

    this.createEmptyRequest = function(p_position, partialRefresh) {
        var request = v_requestBuilder.createEmptyRequest(p_position);
        partialRefresh([p_position], dataSourceUtils.convertRequestToTreeDataArray([request])[0]);
        v_parent.setupChanged("Empty request added");
    };

    this.addChildRequest = function(p_helpPath, p_requestPath, p_position, partialRefresh) {
        var childRequest = v_requestBuilder.addChildRequest(p_helpPath, mcopy(p_requestPath), p_position);
        p_requestPath.push(p_position);
        partialRefresh(p_requestPath, dataSourceUtils.convertRequestToTreeDataArray([childRequest])[0]);
        v_parent.setupChanged('Child request added: "' + childRequest.getData.element + '"');
    };

    this.addEmptyChildRequest = function(p_requestPath, p_position, partialRefresh) {
        var childRequest = v_requestBuilder.addEmptyChildRequest(mcopy(p_requestPath), p_position);
        p_requestPath.push(p_position);
        partialRefresh(p_requestPath, dataSourceUtils.convertRequestToTreeDataArray([childRequest])[0]);
        v_parent.setupChanged("Empty child request added");
    };

    this.copyRequest = function(p_path, partialRefresh) {
        var childRequest = v_requestBuilder.copyRequest(mcopy(p_path));
        p_path[p_path.length - 1] += 1;
        partialRefresh(p_path, dataSourceUtils.convertRequestToTreeDataArray([childRequest])[0]);
        v_parent.setupChanged('Request copied');
    };

    this.convertToSizeOf = function(p_path, refresh) {
        var request = v_this.getRequestFromPath(p_path);
        if (request.getData)
            convertTo(request.getData, "sizeOf");
        else {
            convertTo(request.setData, "sizeOf");
            request.getData = request.setData;
            delete request.setData.content;
            delete request.setData.tp;
            delete request.setData;
        }
        refresh(p_path, "sizeOf");
        v_parent.setupChanged('Request converted to "sizeOf"');
    };

    this.convertToSetData = function(p_path, refresh) {
        var request = v_this.getRequestFromPath(p_path);
        if (request.getData) {
            request.setData = request.getData;
            request.setData.content = "";
            request.setData.tp = 0;
            delete request.getData;
        } else {
            request.getData = request.setData;
            delete request.setData.content;
            delete request.setData.tp;
            delete request.setData;
        }
        selectionOrFilterChanged(request, p_path);
        v_parent.setupChanged('Request converted to "setData"');
    };

    this.convertToDataElementPresent = function(p_path, refresh) {
        var request = v_this.getRequestFromPath(p_path);
        if (request.getData)
            convertTo(request.getData, "dataElementPresent");
        else {
            convertTo(request.setData, "dataElementPresent");
            request.getData = request.setData;
            delete request.setData.content;
            delete request.setData.tp;
            delete request.setData;
        }
        refresh(p_path, "dataElementPresent");
        v_parent.setupChanged('Request converted to "dataElementPresent"');
    };

    this.matches = function(string, path) {
        var request = v_requestBuilder.getRequestCopy(path);
        return JSON.stringify(request).toLowerCase().indexOf(string) != -1;
    };

    function convertTo(request, p_element) {
        var source = request.source;
        var element = request.element;
        var ptcname = request.ptcname;
        var params = request.params;
        if (params == undefined) {
            params = [];
        }

        request.source = "DataSource";
        request.element = p_element;
        request.ptcname = undefined;
        request.filter = undefined;
        request.rangeFilter = undefined;
        request.params = [{
            "paramName": "Source",
            "paramValue": source
        }, {
            "paramName": "Element",
            "paramValue": element
        }];
        if (ptcname != undefined) {
            request.params.push({
                "paramName": "PTCName",
                "paramValue": ptcname
            })
        }

        for (var i = 0; i < params.length; ++i) {
            request.params.push({
                "paramName": "ParamName",
                "paramValue": params[i].paramName
            });
            request.params.push({
                "paramName": "ParamValue",
                "paramValue": params[i].paramValue
            });
        }
    }

    this.isValidToAddRequest = v_requestBuilder.isValidToAddRequest;
    this.isValidToCreateRequest = v_requestBuilder.isValidToCreateRequest;
    this.isValidToMoveRequest = v_requestBuilder.isValidToMoveRequest;

    this.moveRequest = function(p_fromPath, p_toPath, p_position) {
        v_requestBuilder.moveRequest(p_fromPath, p_toPath, p_position);
        v_parent.setupChanged("Request moved");
    };

    this.deleteRequest = function(data) {
        v_requestBuilder.deleteRequest(data);
        v_parent.setupChanged("Request deleted");
    };

    this.getRequest = v_requestBuilder.getRequest;
    this.getRequestFromPath = v_requestBuilder.getRequestFromPath;
    this.getRequestCopy = v_requestBuilder.getRequestCopy;

    ///////////////////// FUNCTIONS FOR FILTER EDITING /////////////////////

    this.getFilterPart = v_requestBuilder.getFilterPart;
    this.getFilterPartCopy = v_requestBuilder.getFilterPartCopy;
    this.addFilterPart = function(p_requestPath, p_filterPath, p_paramName) {
        v_requestBuilder.addFilterPart(p_requestPath, p_filterPath, p_paramName);
        v_parent.setupChanged("Filter added");
    };
    this.deleteFilterPart = function(p_requestPath, p_filterPath) {
        v_requestBuilder.deleteFilterPart(p_requestPath, p_filterPath);
        v_parent.setupChanged("Filter deleted");
    };
    this.convertFilterPartToRequest = function(p_requestPath, p_filterPath, p_helpPath) {
        v_requestBuilder.convertFilterPartToRequest(p_requestPath, p_filterPath, p_helpPath);
        v_parent.setupChanged("Filter type converted to request");
    };
    this.convertFilterPartToDataValue = function(p_requestPath, p_filterPath, p_newValue) {
        v_requestBuilder.convertFilterPartToDataValue(p_requestPath, p_filterPath, p_newValue);
        v_parent.setupChanged("Filter type converted to data value");
    };
    this.isValidToConvertFilterToRequest = v_requestBuilder.isValidToConvertFilterToRequest;
    this.changeParamNameOfFilterRequest = function(p_requestPath, p_filterPath, p_paramName) {
        v_requestBuilder.changeParamNameOfFilterRequest(p_requestPath, p_filterPath, p_paramName);
        v_parent.setupChanged("Filter param name changed");
    };
    this.isValidToAddParamToFilterRequest = v_requestBuilder.isValidToAddParamToFilterRequest;
    this.convertToDataElementPresentInFilter = function(p_requestPath, p_filterPath) {
        var filter = v_requestBuilder.getFilterPart(p_requestPath, p_filterPath);
        var params = filter.request.params;
        convertTo(filter.request, "dataElementPresent");
        for (var i = 0; i < filter.request.params.length; ++i) {
            if (filter.request.params[i].paramValue.dataValue == undefined) {
                filter.request.params[i].paramValue = {"dataValue": filter.request.params[i].paramValue};
            }
        }
        v_parent.setupChanged('Filter element converted to "dataElementPresent"');
    };
}
//# sourceURL=RequestConsole\ViewModels\ViewModel_RequestEditor.js
