/*
 * Copyright (c) 2018-2019 Texas Instruments Incorporated - http://www.ti.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 *  ======== Telnet.syscfg.js ========
 *  Telnet configuration support
 */

"use strict";
/* global exports, system */

//console.log("load: ti/ndk/Telnet");

let util = system.getScript("/ti/ndk/util.js");

/*
 *  ======== modules ========
 *  Express dependencies for other modules
 *
 *  Invoked on any configuration change to the given instance.
 */
function modules(inst)
{
    let modules = new Array();

    modules.push({
        name: "general",
        moduleName: "/ti/ndk/General"
    });

    return (modules);
}

/*
 *  ======== onChange_ipAddrAny ========
 */
function onChange_ipAddrAny(inst, ui)
{
    if (inst.ipAddrAny) {
        inst.ipAddr = "INADDR_ANY";
    }
    else {
        inst.ipAddr = "0.0.0.0";
    }
    ui.ipAddr.readOnly = inst.ipAddrAny
}

/*
 *  ======== validate_instance ========
 *  Validate given instance and report conflicts
 *
 *  This function is not allowed to modify the instance state.
 */
function validate_instance(inst, vo, getRef)
{
    /* config.address */
    if (inst.ipAddr == "INADDR_ANY") {
        /* valid value */
    }
    else if (!util.validateIPAddr(inst.ipAddr)) {
        vo["ipAddr"].errors.push("Invalid IP address");
    }

    /* max connections */
    if(inst.maxCon < 1 || inst.maxCon > 24) {
        vo["maxCon"].errors.push("Must be between 1 and 24");
    }

    /* Server interface ID */
    if(inst.ifIdx < 1 ) {
        vo["ifIdx"].errors.push("Must be greater than 0");
    }

    /* port */
    let port = inst.port;
    let instances = inst.$module.$instances;
    for(let i = 0; i < instances.length; i++) {
        if(instances[i].port == port && instances[i].$name != inst.$name) {
            vo["port"].errors.push(instances[i].$name + " is already using this port number");
        }
    }

    /* callback function */
    if(inst.callbackFxn == "") {
        vo["callbackFxn"].errors.push("Callback function must be provided");
    }
}


/*
 *  ======== longDescription ========
 *  Intro splash on GUI
 */
let longDescription =
    "Create and configure Telnet server instances. Multiple Telnet server " +
    "instances are supported, but each one must be configured to have " +
    "a unique port number.";

/*
 *  ======== config_instance ========
 *  Define the config params of the module (module-wide)
 */
let config_instance = [
    {
        displayName: "Telnet Flags",
        config: [
            {
                name: "IfIdxValid",
                displayName: "Interface index is valid",
                default: false,
                hidden: true,
                longDescription: `
CIS_FLG_IFIDXVALID - Specifies if the IfIdx field is valid.

[More ...](/ndk/ConfigDoc.html#ti_ndk_Telnet_IfIdxValid)`,
                documentation: `
This setting is part of the common argument structure for NDK services. It alters
the Mode field documented in the
[NDK API Guide](NDK_API_Reference.html#common-argument-structure).
        `
            },
            {
                name: "ResolveIP",
                displayName: "Resolve interface to IP address",
                default: false,
                hidden: true,
                longDescription: `
CIS_FLG_RESOLVEIP - Requests that IfIdx be resolved to an IP address before
service execution is initiated.

[More ...](/ndk/ConfigDoc.html#ti_ndk_Telnet_ResolveIP)`,
                documentation: `
This setting is part of the common argument structure for NDK services. It alters
the Mode field documented in the
[NDK API Guide](NDK_API_Reference.html#common-argument-structure).
        `
            },
            {
                name: "CallByIP",
                displayName: "Call using IP",
                default: false,
                hidden: true,
                longDescription: `
CIS_FLG_CALLBYIP - Specifies that the service should be invoked by IP address

[More ...](/ndk/ConfigDoc.html#ti_ndk_Telnet_CallByIP)`,
        documentation: `
This setting is part of the common argument structure for NDK services. It alters
the Mode field documented in the
[NDK API Guide](NDK_API_Reference.html#common-argument-structure).
        `
            },
            {
                name: "RestartIPTerm",
                displayName: "Restart service on IPTERM",
                default: false,
                hidden: true,
                longDescription: `
CIS_FLG_RESTARTIPTERM - A service that is dependent on a valid IP address.

[More ...](/ndk/ConfigDoc.html#ti_ndk_Telnet_RestartIPTerm)`,
                documentation: `
This setting is part of the common argument structure for NDK services. It alters
the Mode field documentated in
[NDK API Guide](NDK_API_Reference.html#common-argument-structure).
        `
            }
        ]
    },
    /*
     * The next three menu items have to do with configuring this service for
     * devices with multiple interfaces. NDK syscfg is targeting E4 devices
     * right now, so these menu options are left hidden until we begin to support
     * multiple interface NDK targets.
     */
    {
        name: "ifIdx",
        displayName: "Server interface ID",
        hidden: true,
        default: 1,
        description: "The physical device index on which the Telnet server " +
            "shall be executed. Must be greater than zero."
    },
    {
        name: "ipAddrAny",
        displayName: "Allow connections on any interface",
        hidden: true,
        onChange: onChange_ipAddrAny,
        default: true
    },
    {
        name: "ipAddr",
        displayName: "IP address",
        hidden: true,
        default: "INADDR_ANY",
        readOnly: true,
        description: "The IP address on which to initiate this service."
    },
    {
        name: "maxCon",
        displayName: "Maximum connections",
        default: 8,  /* TODO - should this be 4?  Code uses 4 as default */
        description: "The maximum number of connections for the telnet " +
            "server (1 - 24).",
        longDescription: `
Sets the maximum number of connections allowed by the telnet server. Must fall
between 1 and 24.

[More ...](/ndk/ConfigDoc.html#ti_ndk_Telnet_maxCon)`,
        documentation: `
More information on the Telnet Server Service can be found in the
[NDK API Guide](NDK_API_Reference.html#telnet-server-service).
`
    },
    {
        name: "port",
        displayName: "Port",
        default: 23,
        description: "The port number which this telnet server will accept " +
            "connections.",
        longDescription: `
The port number that this telnet server instance will accept connections on.
The industry standard telnet port is 23.

[More ...](/ndk/ConfigDoc.html#ti_ndk_Telnet_port)`,
        documentation: `
More information on the Telnet Server Service can be found in the
[NDK API Guide](NDK_API_Reference.html#telnet-server-service).
`
    },
    {
        name: "pCbSrv",
        displayName: "Service report function",
        default: "serviceReport",
        description: "Telnet service reporting function."
    },
    {
        name: "callbackFxn",
        displayName: "Callback function",
        hidden: true,
        default: "ConsoleOpen",
        description: "Telnet callback function.  This is the function which " +
           "contains the telnet server code.",
        longDescription: `
Service report function used by the Telnet server. The default value will use the
report function generated by SysConfig.

[More ...](/ndk/ConfigDoc.html#ti_ndk_Telnet_pCbSrv)`,
        documentation: `
Information on adding your own service report function can be found in the
[NDK User's Guide](NDK_Users_Guide.html#adding-status-report-services).
`
    }
];

/*
 *  ======== tfxn ========
 *  Template helper functions
 */
let tfxn = {
    cisargs_mode: function(inst)
    {
        let flags = [];

        if (inst.IfIdxValid) flags.push("CIS_FLG_IFIDXVALID");
        if (inst.ResolveIP) flags.push("CIS_FLG_RESOLVEIP");
        if (inst.CallByIP) flags.push("CIS_FLG_CALLBYIP");
        if (inst.RestartIPTerm) flags.push("CIS_FLG_RESTARTIPTERM");

        if (flags.length == 0) {
            return ("0");
        }
        else {
            return (flags.join(" | "));
        }
    }
};

/*
 *  ======== base ========
 *  Module definition object
 */
let base = {
    displayName: "Telnet Server",
    description: "NDK Telnet configuration",
    longDescription: longDescription,
    config: config_instance,
    validate: validate_instance,
    moduleStatic: {
        modules: modules
    },

    templates: {
        "/ti/ndk/Config.c.xdt": "/ti/ndk/Telnet.Config.c.xdt"
    },
    tfxn: tfxn
};

/* export the module */
exports = base;
