// 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_Model(p_webAppModel, p_framework, p_extension) {
    "use strict";

    var v_baseModel = p_webAppModel;
    var v_setupModel = v_baseModel.getSetupModel();
    var v_framework = p_framework;
    var v_requestSchema;
    var v_MetaSchema;
    var v_dsRestAPI;

    if (v_baseModel.getAppConfig().lastEditedApp != undefined && window["DsRestAPI"] != undefined) {
        v_dsRestAPI = new DsRestAPI(p_extension);
    } else {
        v_dsRestAPI = {"getHelp": function(callback) {callback(true, {"sources" : []});}};
    }

    v_baseModel.getFileHandler().loadFile('Utils/DsRestAPI/RequestSchema.json', function(ok, data) {
        v_requestSchema = JSON.parse(data);
    });

    v_baseModel.getFileHandler().loadFile('Libs/AJV/json-schema-draft-04.json', function(ok, data) {
        v_MetaSchema = JSON.parse(data);
    });

    ///////////////////// SETUP HANDLING /////////////////////

    this.resetSetupDir = function() {
        v_setupModel.setSetupDirectory(v_baseModel.getAppConfig().appForListingSetups + '/Setups');
    }
    
    this.newSetup = function() {
        v_setupModel.newSetup();
        changeLastEdited(undefined);
        var setup = v_setupModel.getSetup();
        fillDesktopSettings(setup);
        return setup;
    };

    this.deleteSetup = function(name, callback) {
        function setupDeleted(ok) {
            var config = v_baseModel.getAppConfig();
            if (ok && config.lastEditedSetup == name) {
                changeLastEdited(undefined);
            }
            callback(ok)
        }
        v_setupModel.deleteSetup(name, setupDeleted);
    };

    this.switchSetup = function(p_setupName, p_setupLoaded) {
        function setupLoaded(ok, setup, setupName) {
            fillDesktopSettings(setup);
            if (ok) {
                changeLastEdited(setupName);
            }
            p_setupLoaded(ok, setup, setupName);
        }
        v_setupModel.loadSetup(p_setupName, setupLoaded, false);
    };

    this.saveSetup = v_setupModel.saveSetup;

    this.saveSetupAs = function(setupName, callback) {
        function setupSaved(ok) {
            if (ok) {
                changeLastEdited(setupName);
            }
            callback(ok);
        }

        v_setupModel.saveSetupAs(setupName, setupSaved);
    };

    this.listSetups = v_setupModel.listSetups;

    this.setupExists = function(setupName, callback) {
        v_setupModel.setupExists(setupName, callback);
    };

    function fillDesktopSettings(setup) {
        var desktopData = setup.desktop.getData();
        if (desktopData["HtmlEditor"] == undefined) {
            desktopData["HtmlEditor"] = {};
        }
        if (desktopData["RequestEditor"] == undefined) {
            desktopData["RequestEditor"] = {};
        }
    }

    function changeLastEdited(lastEdited) {
        var config = v_baseModel.getAppConfig();
        config.lastEditedSetup = lastEdited;
        v_baseModel.saveAppConfig(config);
    }

    this.globalSetupSearch = v_setupModel.globalSetupSearch;

    this.getSetup = v_setupModel.getSetup;

    ///////////////////// RESOURCE HANDLING /////////////////////

    function listJavascriptResources(locations, callback) {
        new MultipleDirectoryListTask(locations, v_baseModel.getFileHandler()).taskOperation(function(ok, resources) {
            callback(resources.jsfiles);
        });
    }

    this.getViewUrl = function(name) {
        return v_baseModel.getAppConfig().lastEditedApp + "/Views/" + name;
    };

    this.getViewmodelUrl = function(name) {
        return v_baseModel.getAppConfig().lastEditedApp + "/ViewModels/" + name;
    };

    this.deleteFile = function(file, callback) {
        v_baseModel.getFileHandler().delDirectory(file, callback);
    };

    ///////////////////// CONFIG HANDLING /////////////////////

    this.getAppConfig = v_baseModel.getAppConfig;

    this.setEditedApp = function(app, callback) {
        var config = v_baseModel.getAppConfig();
        config.lastEditedApp = app;
        v_setupModel.setSetupDirectory(app + "/Setups");
        v_baseModel.saveAppConfig();
        new JsImportFromConfigTask(app + '/AppConfig.json', v_baseModel.getFileHandler()).taskOperation(function(ok, extension) {
            if (window["DsRestAPI"] != undefined) {
                v_dsRestAPI = new DsRestAPI(extension);
            }
            callback(true);
        });
    };

    this.listEditableApps = function(callback) {
        var result = [];
        var mainConfig = v_baseModel.getMainConfig();
        for (var i = 0; i < mainConfig.availableApps.length; ++i) {
            if (mainConfig.availableApps[i].directory == "WebApplications/CustomizableApp" && mainConfig.availableApps[i].params.customization != undefined) {
                result.push(mainConfig.availableApps[i].params.customization);
            }
        }
        callback(result);
    };

    this.listEditableConfigs = function(callback) {
        var result = [{
            "config": "CustomizableContent/MainConfig.json",
            "schema": "CustomizableContent/MainConfigSchema.json"
        }];
        function filesArrived(data) {
            for (var i = 0; i < data.length; ++i) {
                if (data[i].contentType.endsWith("d")) {
                    result.push({
                        "config": data[i].fileName + "/AppConfig.json",
                        "schema": data[i].fileName + "/AppConfigSchema.json"
                    });
                }
            }
            callback(result);
        }
        v_baseModel.getFileHandler().getDirectory("CustomizableContent", filesArrived);
    };

    ///////////////////// USEFUL FUNCTIONS FOR VIEWMODELS /////////////////////

    this.getRequestSchema = function() {
        return v_requestSchema;
    }
    
    this.getMetaSchema = function() {
        return v_MetaSchema;
    }

    this.getDesktopDataForRequestEditor = function() {
        return v_setupModel.getSetup().desktop.getData()["RequestEditor"];
    };

    this.getDsRestAPI = function() {
        return v_dsRestAPI;
    };

    this.getFileHandler = v_baseModel.getFileHandler;
}

//# sourceURL=RequestConsole\Models\Model.js
