// Copyright (c) 2000-2017 Ericsson Telecom AB                                                       //
// All rights reserved. This program and the accompanying materials are made available under the     //
// terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at //
// http://www.eclipse.org/legal/epl-v10.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_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);
    });

    ///////////////////// 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.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
