/**
 * MVC Nmea Filter Page Model.
 * 
 * Allows user to setup a filter for incoming and outgoing
 * NMEA connections.
 * 
 * @category Webserver
 * @package ATProcessor
 * @author Cameron Guest <cameron@aandtinstruments.com>
 * @version 0.2
 */

class NmeaFilterModel extends ObservableModel
{

    constructor()
    {
        super();
        let self = this;

        this.NMEASentences = [];                // --> NMEA sentence types
        this.NMEAProprietarySentences = [];     // --> NMEA proprietary sentence types.
        this.channels = ["0"];                  // --> Channel ID's
        this.NMEARxFilter = [];                 // --> Receive sentence filter.
        this.NMEATxFilter = [];                 // --> Transmit sentence filter.
        this.NMEANames = ["TCP/UDP"];           // --> NMEA channel names.
        this.baudRates = [];                    // --> NMEA channel baud rates.

        this.init();
    }

    /**
     * Read from the database and setup defaults.
     */
    init()
    {
        let deferred = new $.Deferred();
        let self = this;

        readSection("NMEA").done(function(sectionJSON) 
        {
            let async = [];
            let section = JSON.parse(sectionJSON);

            // Channels
            if (self.channels !== undefined && self.channels !== "")
                self.channels = self.channels.concat(section.channels.split(';'));
            // NMEA Sentences
            if (section.sentencetypes !== undefined && section.sentencetypes !== "")
                self.NMEASentences = section.sentencetypes.trim().split(",");
            // Proprietary Sentences
            if (section.proprietarysentencetypes !== undefined && section.proprietarysentencetypes !== "")
                self.NMEAProprietarySentences = section.proprietarysentencetypes.trim().split(",");

            // Tx Filters
            if (section["nmeatxfilter0"] !== undefined && section["nmeatxfilter0"] !== "")
                self.NMEATxFilter[0] = new Set(section["nmeatxfilter0"].split(","));
            else 
                self.NMEATxFilter[0] = new Set();

            if (section["nmeatxfilter1"] !== undefined && section["nmeatxfilter1"] !== "")
                self.NMEATxFilter[1] = new Set(section["nmeatxfilter1"].split(","));
            else 
                self.NMEATxFilter[1] = new Set();

            if (section["nmeatxfilter2"] !== undefined && section["nmeatxfilter2"] !== "")
                self.NMEATxFilter[2] = new Set(section["nmeatxfilter2"].split(","));
            else 
                self.NMEATxFilter[2] = new Set();
        
            for (let i = 0; i < self.channels.length; i++) 
            {
                let channel = self.channels[i];
                let c = parseInt(channel);
                if ((c & (1 << 6)) && (c & 0x03) <= 2)
                {
                    if (section["nmeatxfilter" + channel] !== undefined && section["nmeatxfilter" + channel] !== "")
                    {
                        self.NMEATxFilter[channel] = new Set(section["nmeatxfilter" + channel].split(","));
                    }
                    else self.NMEATxFilter[channel] = new Set();
                }
            }

            for (let i = 0; i < self.channels.length; i++) {
                let channel = self.channels[i];

                // Rx Filters
                if(section["nmearxfilter" + channel] !== undefined && section["nmearxfilter" + channel] !== "")
                    self.NMEARxFilter[channel] = new Set(section["nmearxfilter" + channel].split(","));
                else 
                    self.NMEARxFilter[channel] = new Set();

                // Names
                async.push(readSingle("NMEA" + channel, "Name").done(function(name) {
                    if (name) self.NMEANames[channel] = name;
                }));

                // Baud Rates
                async.push(readSingle("NMEA" + channel, "BaudRate").done(function(baudRate) {
                    self.baudRates[channel] = baudRate || "4800";
                }));
            }

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

        return deferred.promise();
    }

    persistData() 
    {
        let database = [];

        for (const channel of this.channels)
        {
            let rx = [...this.NMEARxFilter[channel]]; // Turn set back to Array to use .join
            database.push({section: 'nmea', key: 'nmearxfilter' + channel, value: rx.join(",")});

            if (channel < 3 || ((channel & (1 << 6)) && ((channel & 3) <= 2)))
            {
                let tx = [...this.NMEATxFilter[channel]];
                database.push({section: 'nmea', key: 'nmeatxfilter' + channel, value: tx.join(",")});
            }

            if (channel != 0 )
            {
                database.push({section: 'nmea' + channel, key: 'baudrate', value: this.baudRates[channel]});
            }
        }

        return writeToDatabase(database, "NMEAFilter");
    }
}
