/**
 * Data Output MVC Model
 * 
 * Defines network connections
 * 
 * @category    Webserver
 * @package     ATProcessor
 * @author      Sam Meredith <sam@aandtinstruments.com>
 * @version     0.1
 */

const _MIN_PORT = 1024;
const _MAX_PORT = 32767;
const maxNetworkConnections = 8;
const defaultConnection = {
    "connectionname": "Network Connection",
    "adaptoraddress": "",
    "connectiontype": "UDP Output",
    "enabled": "0",
    "format": "Expedition",
    "port": "5010",
    "udpaddress": ""
};


class DataOutputModel extends ObservableModel
{
    constructor()
    {
        super();

        this.distributionData = {};     // Shared distribution properties
        this.savedConnections = {};     // Network objects

        this.init();
    }

    // Add a new connection to the set of saved connections
    addConnection(connectionData) {
        // Get next available connection number
        for (var i = 0; i < maxNetworkConnections; i++) {
            if (this.savedConnections[i] === undefined)
                break;
        }

        this.savedConnections[i] = connectionData;
    }

    // Get the list of available adaptors
    get adaptors() {
        return this.distributionData.ipaddresses.split(';');
    }

    // Get the list of available connection types
    get connectionTypes() {
        return this.distributionData.connectiontype.split(',');
    }

    // Get the list of available formats
    get formats() {
        return this.distributionData.formats.split(";");
    }

    // Get the list of configured connections
    get networkConnections() {
        let connections = [];

        //If the database gets NaN in it (not sure how it happened, but it did) then problems
        let connectionArray = $.grep(this.distributionData.networkconnections.split(','),
            connection => $.isNumeric(connection));
        if (connectionArray.length == 0)
            connections = [1];
        else
            connections = connectionArray.map(connection => parseInt(connection, 10));

        return connections;
    }

    get outputFrequency() {
        return this.distributionData.outputfrequency;
    }
    set outputFrequency(frequency) {
        this.distributionData.outputfrequency = frequency;
    }

    // Populate the model
    init() {
        let self = this;

        // Load general distribution properties
        readSection("Distribution").done(function(sectionJSON) {
            self.distributionData = JSON.parse(sectionJSON);

            // Make sure an 'output frequency' is included in self.distributionData object,
            // in case the database does not contain that key.
            if (!self.distributionData.outputfrequency || self.distributionData.outputfrequency.length === 0)
                self.distributionData.outputfrequency = 1;

            let async = [];
            // Populate existing network containers
            for (let i = 0; i < self.networkConnections.length; i++) {
                let deferred = new $.Deferred();
                async.push(deferred.promise());

                let connectionNum = self.networkConnections[i];
                readSection('NetworkConnection:' + connectionNum).done(function(sectionJSON) {
                    self.savedConnections[parseInt(i)] = $.extend({}, defaultConnection, JSON.parse(sectionJSON));
                    deferred.resolve();
                });
            }

            $.when.apply($, async).then(function() {
                self.notifyAll();
            });
        });
    }

    setAdaptorAddress(idx, address) {
        this.savedConnections[idx].adaptoraddress = address; 
    }

    setBroadcast(idx, broadcast) {
        this.savedConnections[idx].udpbroadcast = broadcast;
    }

    setConnectionAddress(idx, address) {
        this.savedConnections[idx].udpaddress = address;
    }

    setConnectionType(idx, type) {
        this.savedConnections[idx].connectiontype = type;
    }

    setEnabled(idx, enabled) {
        this.savedConnections[idx].enabled = enabled;
    }

    setFormat(idx, format) {
        this.savedConnections[idx].format = format;
    }

    setFrequency(idx, freq) {
        this.savedConnections[idx].outputfrequency = freq;
    }

    setPort(idx, port) {
        this.savedConnections[idx].port = port;
    }

    setName(idx, name) {
        this.savedConnections[idx].connectionname = name;
    }

    // Write data out to the database
    persistData()
    {
        let connectionArray = [];
        let databaseArray = [];
        let self = this;

        for (var idx in this.savedConnections) {
            if (this.savedConnections.hasOwnProperty(idx)) {
                connectionArray.push(idx);

                let section = "NetworkConnection:" + idx;
                Object.keys(this.savedConnections[idx]).forEach(function(key) {
                    databaseArray.push({ section : section, key : key, value : self.savedConnections[idx][key] });
                });
            }
        }
        databaseArray.push({ section: 'Distribution', key : 'OutputFrequency', value : self.distributionData.outputfrequency });
        databaseArray.push({ section: 'Distribution', key : 'NetworkConnections', value : connectionArray.join(',') });

        return writeToDatabase(databaseArray, "Networking");
    }
}