/**
 * MVC for expedition channel import.
 * 
 * @category Webserver
 * @package ATProcessor
 * @author Cameron Guest <cameron@aandtinstruments.com>
 * @version 0.1
 * 
 */

const NUM_REMOTE_CHANNELS = 10;
const DEFAULT_IMPORT_STRING = "0,,No Channel";
 
class ExternalModel extends ObservableModel {

    constructor() {
        super();

        this.externalData = [];
        this.channelData = [];

        this.init();
    }

    init() {

        let self = this;

        readSection("Expedition").done(function(expeditionJSON) {

            let expeditionSection = JSON.parse(expeditionJSON);
            let channelArray = expeditionSection.channels.split(',');

            // Setup Channel Definitions.
            for (let i = 0; i < channelArray.length; i += 2) {
                self.channelData.push({ 'channel': channelArray[i], 'name': channelArray[i + 1] });
            }

            // Setup User Configuration.
            for (let i = 0; i < NUM_REMOTE_CHANNELS; i++) {
                self.externalData.push((expeditionSection["remote" + i] || DEFAULT_IMPORT_STRING).split(','));
            }

            // Sort Channels Alphabetically
            self.channelData.sort(function(a, b) {
                return a.name.localeCompare(b.name, 'en', {numeric: true});
            });

            self.notifyAll();
        });
    }

    persistData() {

        let dbArray = [];

        for (let i = 0; i < this.externalData.length; i++) {
            dbArray.push({'section': 'Expedition', 'key': 'Remote' + i, 'value': this.externalData[i].join(',')});
        }

        return writeToDatabase(dbArray, 'Expedition');
    }

    // Check if an expedition channel is already in use.
    isExpeditionChannelInUse(exChannel) {

        for (let i = 0; i < this.externalData.length; i++) {

            if (this.externalData[i][0] == exChannel)
                return true;
        }

        return false;
    }
}

class ExternalController extends BasicController {

    constructor(model) {
        super(model);
    }

    changeExpeditionChannel(e) {

        let $dataRow = $(e.target).closest('.exp-user-data');
        let dataIndex = $dataRow.attr('remote-index');
        let expChannel = $(e.target).val();

        if (dataIndex) {

            // Don't allow multiple remotes to be mapped to the same expedition channel. 
            if (expChannel != 0 && this.model.isExpeditionChannelInUse(expChannel)) {
                $(e.target).val(this.model.externalData[dataIndex][0]);
                $('#dialog-text').text('Cannot map the same expedition channel to multiple fastnet channels.');
                $('#dialog').dialog({   
                    title: "Duplicate Mapping",
                    buttons: {
                        Ok: function() {
                            $(this).dialog('close');
                        }
                    }
                }).dialog('open');
            }
            else {
                this.model.externalData[dataIndex][0] = expChannel;
                let displayName = $(e.target).children('option:selected').text().trim();

                if (displayName.length > 10) {
                    let shortName = "";
                    for (let word of displayName.split(' ')) {
                        shortName += word.substring(0, 1);
                    }

                    shortName = shortName.substring(0, 10);
                    $dataRow.find('.exp-name-input').val(shortName);
                    this.model.externalData[dataIndex][2] = shortName;
                }
                else {
                    displayName = displayName.substring(0, 10);
                    $dataRow.find('.exp-name-input').val(displayName.substring(0, 10));
                    this.model.externalData[dataIndex][2] = displayName;
                }
            }
        }
    } 

    changeFastnetName(e) {
        let idx = $(e.target).closest('.exp-user-data').attr('remote-index');

        if (idx) {
            this.model.externalData[idx][2] = $(e.target).val();
        }
    }
}

class ExternalView extends BasicView {

    constructor(controller) {
        super(controller);
    }

    bindEvents() {
        super.bindEvents();

        $('#expedition-content').on('change', '.exp-name-input', this.controller.changeFastnetName.bind(this.controller));
        $('#expedition-content').on('change', '.exp-channel-select', this.controller.changeExpeditionChannel.bind(this.controller));
    }

    update(model) {

        let channelOptions = '<option value="0">No Channel</option>';

        // Build the expedition channel options list
        for (let i = 0; i < model.channelData.length; i++) {
            let data = model.channelData[i];
            channelOptions += '<option value="' + data.channel + '">' + (data.name || "Unknown") + '</option>';
        }

        // Add each user data field.
        for (let i = 0; i < model.externalData.length; i++) {
            let expData = model.externalData[i];

            $('#expedition-content').append(
                    '<div class="flex-row exp-user-data" remote-index="' + i + '">'
                +       '<div class="flex-fourth justify-center">'
                +           (239 + i) + ' - Remote ' + i
                +       '</div>'
                +       '<div class="flex-fourth justify-center">'
                +           '<select class="exp-channel-select">' + channelOptions + '</select>'
                +       '</div>'
                +       '<div class="flex-fourth justify-center">'
                +           '<input class="exp-name-input" type="text" maxlength="10" value="' + (expData[2] || "") + '">'
                +       '</div>'
                +       '<div class="flex-fourth justify-center">'
                +           '<div class="field-container" data-field="0x' + (0x900 + i).toString(16) + '"'
                +               'data-sender="Expedition" data-instance="20" id="exp-chan-' + i + '">'
                +       '</div>'
                +   '</div>'
            );

            $('.exp-user-data[remote-index="'+ i +'"] .exp-channel-select').val(expData[0]);
        }
    }
}