/**
 * Model, View, Controller for Navigation page.
 * 
 * @category    Webserver
 * @package     ATProcessor
 * @author      Sam Meredith <sam@aandtinstruments.com>
 * @version     0.1
 */

//----------------------------------------
// Model
//----------------------------------------
class NavigationModel extends ObservableModel
{
    constructor()
    {
        super();

        this.sources = {};
    }

    //----------------------------------------
    // Getters/Setters
    //----------------------------------------
    // get canbusDevice() { return this.sources.canbus; }

    get instance() { return this.data.instance; }
    set instance(instance) { this.data.instance = instance; }

    get listOfCanDevices() { return this.sources.listOfCanDevices; }

    get nmeaPorts() { return this.sources.nmea0183; }

    get source() { return this.data.source; }
    set source(source) { this.data.source = source; }

    get uniqueid() { return this.data.uniqueid; }
    set uniqueid(uniqueid) { this.data.uniqueid = uniqueid; }

    init()
    {
        let self = this;
        let defaults = {
            "source": "",
            "instance": 1,
            "uniqueid": "0"
        };

        $.when(readSection("Navigation"), readSingle("NMEA", "Channels"), /*readSingle("CanbusReceive", "Navigation"),*/ readSingle("CanSource", "Navigation")).done(
            function(navigationSection, nmeaChannels, /*canbusReceiveNav,*/ canSourceNavSection)
        {
            let async = [];

            self.data = $.extend({}, defaults, JSON.parse(navigationSection[0]));

            // Load in NMEA0183 Ports
            let nmeaPorts = {};
            nmeaChannels[0].split(';').forEach(function(element) {
                async.push(readSingle("NMEA" + element, "Name").done(function(name) {
                    nmeaPorts[element] = name;
                }));
            });

            // Load in data for CANbus source
            /*let canData = {};
            async.push(readSection("CanDevices:" + canbusReceiveNav[0]).done(function(deviceSection) {
                canData.id = canbusReceiveNav[0];
                canData.name = JSON.parse(deviceSection).model;
                canData.address = JSON.parse(deviceSection).address;
            }));*/

            // Reads Canbus Sources from database
            var canbusDevices = [];
            let def = new $.Deferred();
            async.push(def.promise());

            let canDevicesIds = canSourceNavSection[0].split(";").filter(Boolean); // Filter removes empty strings ("")

            let deviceAsync = [];
            canDevicesIds.forEach(function(id) {
                deviceAsync.push(readSection("CanDevices:" + id).done(function(response) {
                    let deviceInfo = JSON.parse(response);

                    canbusDevices.push({ 
                        "uniqueid" : id,
                        "model" : (deviceInfo.model || ""),
                        "address" : (deviceInfo.address || 0),
                        "serialNumber" : (deviceInfo.serialnumber || ""),
                        "displayName": (deviceInfo.model || "") + " [" + (deviceInfo.serialnumber || "") + "]",
                        "isConnected" : true
                    });
                }))
            });

            $.when.apply($, deviceAsync).then(function() {
                def.resolve();
            });

            $.when.apply($, async).then(function() {
                self.sources.nmea0183 = nmeaPorts;
                // self.sources.canbus = canData;
                self.sources.listOfCanDevices = canbusDevices;

                // If uniqueid for source isn't stored in listOfCanDevices, it is probably not connected. Add it to the list.
                if (self.data.uniqueid !== "" && self.data.uniqueid !== "0") {
                    if (self.sources.listOfCanDevices.find(device => device.uniqueid === self.data.uniqueid) === undefined) {
                        self.sources.listOfCanDevices.push({ 
                            "uniqueid" : self.data.uniqueid,
                            "model" : "",
                            "address" : "0",
                            "serialNumber" : "",
                            "displayName": "Unconnected Device [ID:" + self.data.uniqueid + "]",
                            "isConnected" : false
                        });
                    }
                }  

                self.notifyAll();
            });
        });
    }

    persistData()
    {
        let databaseArray = [];

        $.each(this.data, function(key, value) {
            databaseArray.push( { section: "Navigation", key: key, value: value } );
        });

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

//----------------------------------------
// Controller
//----------------------------------------
class NavigationController extends BasicController
{
    constructor(model)
    {
        super(model);
    }

    changeInstance(e)
    {
        this.model.instance = $(e.target).val();
        this.model.notifyAll();
    }

    changeSource(e)
    {
        this.model.source = $(e.target).val();
        this.model.notifyAll();
    }

    redirectCANbus(e)
    {
        window.location.href = "canFilter.php";
    }

    redirectNMEA(e)
    {
        window.location.href = "nmeaFilter.php";
    }

    changeCanbusDevice(e) {
        this.model.uniqueid = $(e.target).val();
        this.model.notifyAll();
    }
}

//----------------------------------------
// View
//----------------------------------------
class NavigationView extends BasicView 
{
    constructor(controller)
    {
        super(controller);

        this.controller.model.init();
    }

    bindEvents() 
    {
        super.bindEvents();

        $('#nav-source-select').on('change', this.controller.changeSource.bind(this.controller));
        $('#source-select-container').on('click', '#nmea-configuration-redirect', this.controller.redirectNMEA.bind(this.controller));
        $('#source-select-container').on('click', '#canbus-configuration-redirect', this.controller.redirectCANbus.bind(this.controller));
        $('#source-select-container').on('change', '#nmea-instance-select', this.controller.changeInstance.bind(this.controller));
   
        $('#source-select-container').on('change', '#can-devices', this.controller.changeCanbusDevice.bind(this.controller));
    }

    drawCANbusSource(model)
    {
        $('#source-select-container').empty();

        let optionString = "<option value='0' data-address='0'>No Device</option>";
        model.listOfCanDevices.forEach(function(device) {
            optionString += "<option value='" + device.uniqueid + "' data-address='" + device.address + "'>" + device.displayName + "</option>";
        });

        $('#source-select-container').append(
			    '<div class="flex-row">'
            +	    '<div class="flex-heading">'
            +           '<h2>CANbus Device:</h2>'
            +       '</div>'
            +       '<select id="can-devices">'
            +           optionString
            +       '<select>'
			+   '</div>'
        );

        $('.field-container').attr('data-sender', "Canbus");

        // Set selected option as the one that has been read from the database
        $('#can-devices').find('option[value="' + model.uniqueid + '"]').prop('selected', true);

        const canDevice = model.listOfCanDevices.find(device => {
            return device.uniqueid === model.uniqueid;
        });

        let address = "0";
        if (canDevice !== undefined)
        {
            address = canDevice.address;

            if (!canDevice.isConnected)
                $('#can-devices').addClass('bad-source');
        }
        else
            $('#can-devices').addClass('bad-source');

        $('.field-container').attr('data-instance', address);
    }

    drawNMEASource(model)
    {
        let optionString = "";
        $.each(model.nmeaPorts, function(key, value) {
            if ($.isNumeric(key) && value != "")
            optionString += '<option value="' + key + '" ' + (model.instance == key ? "selected" : "" ) + '>' + value + '</option>'
        });

        $('#source-select-container').append(
			    '<div class="flex-row">'
			+       '<div class="flex-heading">'
			+           '<h2>NMEA0183 Channel:</h2>'
			+       '</div>'
            +       '<select id="nmea-instance-select">' + optionString + '</select>'
            +       '<a class="button button-gray button-medium redirect-button" id="nmea-configuration-redirect">NMEA0183 Settings</a>'
			+   '</div>'
        );

        let selectedOptionObj = $('#nmea-instance-select').find('option[value="' + model.instance + '"]');
        
        if (selectedOptionObj.length == 0) {
            model.instance = $('#nmea-instance-select').val();
            selectedOptionObj = $('#nmea-instance-select').find('option[value="' + model.instance + '"]');
        }

        selectedOptionObj.prop('selected', true);

        $('#nmea-instance-select').find('option[value="' + model.instance + '"]').prop('selected', true);
        
        $('.field-container').attr('data-sender', "NMEA0183");
        $('.field-container').attr('data-instance', model.instance);
    }

    update(model)
    {
        //console.log(model);
        $('#nav-source-select option[value="' + model.source + '"]').prop('selected', true);

        $('#source-select-container').empty();
        if (model.source == "nmea0183")
        {
            this.drawNMEASource(model);
        }
        else if (model.source == "canbus")
        {
            this.drawCANbusSource(model);
        }
        else if (model.source == "expedition")
        {
            $('.field-container').attr('data-sender', "Expedition");
            $('.field-container').attr('data-instance', "20");
        }
        else
        {
            $('.field-container').attr('data-sender', "NoSource");
            $('.field-container').attr('data-instance', "n/a");
        }
    }
}
