/**
 * Display handler for rudder input.
 * 
 * @category Webserver
 * @package ATProcessor
 * @author Sam Meredith <sam@aandtinstruments.com>
 * @version 0.1
 * 
 */

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

        this.availableSources = [];
        this.data = {
            source : "no source",
            instance: "0",
            uniqueid : "0"
        };

        this.listOfCanDevices = [];
    }

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

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

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

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

    init() {
        let async = new Array();
        let deferred = new $.Deferred();
        let self = this;

        async.push(
            readSection("Rudder").done(function(rudderSection) {
                self.data = $.extend(self.data, JSON.parse(rudderSection));
            })
        );

        async.push(
            getSources("Rudder").done(function(sources, canbusDevices) {
                self.availableSources = sources;
                self.availableSources.unshift(
                    { displayName: "No Source", internalName: "no source" },
                    { displayName: "ATPilot", internalName: "atpilot" }
                );

                self.listOfCanDevices = canbusDevices;
            })
        );

        $.when.apply($, async).then(function() {

            // 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.listOfCanDevices.find(device => device.uniqueid === self.data.uniqueid) === undefined) {
                    self.listOfCanDevices.push({ 
                        "uniqueid" : self.data.uniqueid,
                        "model" : "",
                        "address" : "0",
                        "serialNumber" : "",
                        "displayName": "Unconnected Device [ID:" + self.data.uniqueid + "]",
                        "isConnected" : false
                    });
                }
            }   

            self.notifyAll();
            deferred.resolve();
        });

        return deferred.promise();
    }

    persistData() {

        var databaseArray = new Array();

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

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

class RudderInputController extends BasicController {
    constructor(model) {

        super(model);
    }

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

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

    changeSource(e) {

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

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

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

class RudderInputView extends BasicView {
    constructor(controller) {
        super(controller);

        this.controller.model.init();
    }

    bindEvents() {
        super.bindEvents();

        $('#sensor-source-select').on('change', this.controller.changeSource.bind(this.controller));

        $('#source-config-container').on('click', '#canbus-configuration-redirect', this.controller.canbusRedirect.bind(this.controller));
        $('#source-config-container').on('click', '#nmea-configuration-redirect', this.controller.nmeaRedirect.bind(this.controller));
        $('#source-config-container').on('change', '#nmea-instance-select', this.controller.changeInstance.bind(this.controller));

        $('#source-config-container').on('change', '#can-devices', this.controller.changeCanbusDevice.bind(this.controller));
    }

    drawCanbusContainer(model) {
        $('#source-config-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-config-container').append(
                '<div>'
            +       '<div class="flex-row">'
            +           '<div class="flex-heading">'
            +               '<h2>CANbus Device:</h2>'
            +           '</div>'
            +           '<select id="can-devices">'
            +               optionString
            +           '<select>'
            +       '</div>'
            +   '</div>'
        );

        $('#rudder-data').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');

        $('#rudder-data').attr('data-instance', address);

        $('#source-config-container').show();
    }

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

        let device = model.availableSources.find(source => (source.internalName == dataSouceDisplayNames.NMEA.toLowerCase()));
        device.ports.forEach(function(port) {
            $('#nmea-instance-select').append(
                '<option value="' + port.internalName + '">' + port.displayName + '</option>'
            );
        });

        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);

        $('#rudder-data').attr('data-sender', 'nmea0183');
        $('#rudder-data').attr('data-instance', model.instance);
    }

    update(model)
    {
        console.log(model);

        $('#sensor-source-select').empty();
        model.availableSources.forEach(function(source) {
            if (source.hasOwnProperty("internalName") && source.hasOwnProperty("displayName")) {
                $('#sensor-source-select').append(
                    '<option value="' + source.internalName + '">' + source.displayName + '</option>'
                );
            }
        });
        let source = $('#sensor-source-select').find('option[value="' + model.source + '"]');
        if (source.length == 0) {
            $('#sensor-source-select').css('outline', '1px solid red');
        } else {
            source.prop('selected', true);
        }

        switch (model.source)
        {
            case "canbus":
                this.drawCanbusContainer(model);
                break;

            case "nmea0183":
                this.drawNMEAContainer(model);
                break;

            case "atpilot":
            case "fastnet":
            default:
                $('#source-config-container').hide();
                if (model.source.includes("main interface") || model.source.includes("analogue")) {

                    $('#rudder-data').attr('data-sender', "Processor");
                    $('#rudder-data').attr('data-instance', 0);
                }
                else {
                    
                    $('#rudder-data').attr('data-sender', model.source);
                    $('#rudder-data').attr('data-instance', 0);
                }
                break;
        }
    }
}
