/**
 * Class definitions for CANbus page.
 * 
 * @category Webserver
 * @package ATProcessor
 * @author Sam Meredith <sam@aandtinstruments.com>
 * @version 0.1
 * 
 */

 /**
 * Defines input and output filter for CANbus
 */
class CANbusModel extends ObservableModel {
    constructor() {
        super();

        this.canDevices = {}; // The list of available CANbus devices
        this.canSources = {}; // The list of CANbus devices for each source type
        // this.receiveDevices = {}; // The devices to receive from
        // this.receiveSourceTypes = []; // The CANbus source types we can receive
        this.transmitDevices = {}; // Whether or not Tx is enabled
        this.transmitSourceTypes = []; // The CANbus source types we can transmit
    }

    init() {
        let self = this;

        $.when(/*readSingle("Distribution", "CanReceiveList"),*/ readSingle("Distribution", "CanTransmitList"),
            readSection("CanDevices", 0), /*readSection("CanbusReceive"),*/ readSection("CanbusTransmit"),
            readSection("CanSource")).done(
            function(/*rxList,*/ txList, canDeviceSection, /*canReceiveSection,*/ canTransmitSection, canSourceSection) {

            let async = [];

            let canDevices = $.extend({}, JSON.parse(canDeviceSection[0]));
            $.each(canDevices, function(key, value) {
                async.push(readSection("CanDevices:" + key).done(function(deviceJSON) {
                    let deviceSection = JSON.parse(deviceJSON);
                    self.canDevices[key] = { 
                        "serial" : deviceSection["serialnumber"],
                        "model" : deviceSection["model"]
                    };
                }));
            })

            self.canSources = $.extend({}, JSON.parse(canSourceSection[0]));
            $.each(self.canSources, function(key, value) {
                self.canSources[key] = value.split(';').map(x => x.toLowerCase());
            })
            // self.receiveDevices = $.extend({}, JSON.parse(canReceiveSection[0]));
            self.transmitDevices = $.extend({}, JSON.parse(canTransmitSection[0]));

            self.transmitSourceTypes = txList[0].split(',');
            // self.receiveSourceTypes = rxList[0].split(',');

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

    persistData() {
        var databaseArray = new Array();

        /*$.each(this.receiveDevices, function(key, value) {
            databaseArray.push( { 'section' : 'CanbusReceive', 'key' : key, 'value' : value } );
        });*/

        $.each(this.transmitDevices, function(key, value) {
            databaseArray.push( { 'section' : 'CanbusTransmit', 'key' : key, 'value' : value } );
        });

        return writeToDatabase(databaseArray, 'CanBusFilter');
    }
}

/**
 * View -> Model interaction for CANbus page
 */
class CANbusController extends BasicController {
    constructor(model) {
        super(model);
    }

    /*changeRxDevice(e) {
        this.model.receiveDevices[$(e.target).attr('data-source').toLowerCase()] = $(e.target).val();

        if ($(e.target).find('option:selected').hasClass('can-invalid')) {
            $(e.target).addClass('can-invalid');
        } else {
            $(e.target).removeClass('can-invalid');
        }
    }*/

    toggleTx(e) {
        this.model.transmitDevices[$(e.target).attr('data-source').toLowerCase()] = $(e.target).is(':checked');
    }
}

/**
 * Handle display for CANbus page
 */
class CANbusView extends BasicView {
    constructor(controller) {
        super(controller);

        this.controller.model.init();
    }

    bindEvents() {
        super.bindEvents();

        // $('.canbus-grid').on('change', '[name="rx-select"]', this.controller.changeRxDevice.bind(this.controller));
        $('.canbus-grid').on('change', '[name="tx-select"]', this.controller.toggleTx.bind(this.controller));
    }

    update(model) {
        let canDeviceOptions = '<option value="">No Device</option>';
        $.each(model.canDevices, function(key, value) {
            canDeviceOptions +=
                '<option value="' + key + '">' + value["model"] + ' (' + value["serial"] + ')</option>'
            ;
        });

        // Draw Rx sources
        /*model.receiveSourceTypes.forEach(function(source, index) {
            let row = $(
                    '<div class="grid-item">' + source + '</div>'
                +   '<div class="grid-item">'
                +       '<select name="rx-select" data-source="' + source + '">' + canDeviceOptions + '</select>'
                +   '</div>'
                +   '<div class="grid-item">'
                +       '<input name="tx-select" type="checkbox" data-source="' + source + '" '
                +           (model.transmitDevices[source.toLowerCase()] ? "checked" : "") + '>'
                +   '</div>'
            );
            // Check if device is valid for this source
            let sourceList = model.canSources[source.toLowerCase()] || [];
            row.find('select option').each(function(index) {
                if (index > 0 && !sourceList.includes($(this).val().toLowerCase())) {
                    $(this).addClass('can-invalid');
                }
            });

            // Set the selected device
            let rxFrom = model.receiveDevices[source.toLowerCase()] || "";
            row.find('select option[value="' + rxFrom + '"]').prop('selected', true);
            if (row.find('option:selected').hasClass('can-invalid')) {
                row.find('select').addClass('can-invalid');
            }

            $('.canbus-grid').append(row);
        });*/
        // Draw remaining Tx sources
        model.transmitSourceTypes.forEach(function(source, index) {
            //if (!model.receiveSourceTypes.includes(source)) {
                $('.canbus-grid').append(
                        '<div class="grid-item">' + source + '</div>'
                    // +   '<div class="grid-item"></div>'
                    +   '<div class="grid-item">'
                    +       '<input name="tx-select" type="checkbox" data-source="' + source + '" '
                    +           (model.transmitDevices[source.toLowerCase()] ? "checked" : "") + '>'
                    +   '</div>'
                );
            //}
        });
    }
}