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

const RxExclusion = [
    "MXS",
    "MMB"
];

const TxExclusion = [
    "TCF",
    "FEC",
    "ASHR",
    "DYN",
    "RTE",
    "WPL",
    "ZTG"
];

class NmeaFilterView extends BasicView
{
    bindEvents()
    {
        super.bindEvents();
        $('.nmea-filter').on(
            'change', '[type=checkbox]', this.controller.UpdateFilter.bind(this.controller));
        $('.nmea-proprietary-filter').on(
            'change', '[type=checkbox]', this.controller.UpdateFilter.bind(this.controller));
        $('.nmea-filter').on(
            'change', 'select', this.controller.UpdateBaud.bind(this.controller));
    }

    /**
     * Build a row of TxRx Checkboxes
     * @param {Array[string]} ids - Channel ID's.
     * @param {string} type - Name of the NMEA sentence.
     * @param {Array[Set]} rx - Rx Filters. 
     * @param {Array[Set]} tx - Tx Filters.
     */
    BuildTxRxRow(ids, type, rx, tx)
    {
        let html = '';
        for(let i = 0; i < ids.length; i++)
        {
            // NMEA interface boards can TX on ports 1 and 2
            let interfaceBoardTX = (ids[i] & (1 << 6)) && ((ids[i] & 3) <= 2);
            // Main interface board can also TX on ports 1 and 2
            let useTx = (ids[i] < 3 || interfaceBoardTX) ? true : false;
            html += this.BuildTxRxCell(ids[i], type, rx[ids[i]], tx[ids[i]], useTx);
        }
        return html;
    }

    /**
     * Build a row of Baud Rate dropdown menus.
     * @param {Array[string]} ids - Channel ID's
     * @param {Array[string]} baudRates - Channel Selected Baud Rates.
     */
    BuildBaudRateRow(ids, baudRates)
    {
        let html = '';
        for(let i = 0; i < ids.length; i++)
            html += this.BuildBaudRateCell(ids[i], baudRates[ids[i]]);
        return html;
    }

    /**
     * Build a row containing the name of every port.
     * @param {Array[string]} ids - Channel ID's
     * @param {Array[string]} ports - Channel Names. 
     */
    BuildPortRow(ids, ports)
    {
        let html = '';
        for(let i = 0; i < ids.length; i++)
            html += '<div class="cell inner-cell"><h2>' + ports[ids[i]] + '</h2></div>';
        return html;
    }


    /**
     * Build a cell containing a dropdown to set the channels baud rate.
     * @param {string} channelId The unique id of the channel. 
     * @param {string} baudRate  The currently selected baud rate.
     */
    BuildBaudRateCell(channelId, baudRate)
    {
        let html = '';
        if(channelId !== "0")
        {
            html += '\
            <div class="cell inner-cell">\
                <select class="database-input" data-key="BaudRate" data-section="' + channelId + '" id="baud-select">\
                    <option value="4800"' + ((baudRate === "4800" || baudRate === "")?"selected":"") + '>4800</option>\
                    <option value="9600"' + (baudRate === "9600"?"selected":"") + '>9600</option>\
                    <option value="19200"' + (baudRate === "19200"?"selected":"") + '>19200</option>\
                    <option value="38400"' + (baudRate === "38400"?"selected":"") + '>38400</option>\
                    <option value="57600"' + (baudRate === "57600"?"selected":"") + '>57600</option>\
                    <option value="115200"' + (baudRate === "115200"?"selected":"") + '>115200</option>\
                </select>\
            </div>';
        }
        else
        {
            // Don't generate for TCP/IP field.
            html += '<div class="cell inner-cell"></div>';
        }
        
        return html;
    }

    /**
     * Build a cell containing Rx and Tx checkboxes.
     * @param {string} channelId The unique id of the channel.
     * @param {string} type The name of the NMEA0183 sentence.
     * @param {Set[string]} rx Set containing channel's enabled Rx sentences.    
     * @param {Set[string]} tx Set containing channel's enabled Tx sentences. 
     * @param {bool} useTx Determine if this cell requires a Tx checkbox.
     */
    BuildTxRxCell(channelId, type, rx, tx, useTx)
    {   
        let html = '<div class="cell inner-cell">';

        // Build the Rx Checkbox.
        if (!RxExclusion.includes(type))
        {
            html += 'Rx&nbsp;\
                <input type="checkbox" id="' + type + '-Rx-' + channelId + '" data-channelNo="' + channelId + '"\
                    name="Receive" value="' + type + '" ' + (rx.has(type) ? 'checked' : '') + '>';
        }
        else
        {
            html += '<div class="label-disabled">Rx&nbsp;</div>\
                <input type="checkbox" id="' + type + '-Rx-' + channelId + '" data-channelNo="' + channelId + '"\
                    name="Receive" value="' + type + '" disabled >';
        }

        // Maybe need to build the Tx Checkbox.
        if(useTx)
        {
            if (!TxExclusion.includes(type))
            {
                html += 'Tx&nbsp;\
                    <input type="checkbox" id="' + type + '-Tx-' + channelId + '" data-channelNo="' + channelId + '"\
                        name="Transmit" value="' + type + '" ' + (tx.has(type) ? 'checked' : '') + '>';
            }
            else
            {
                html += '<div class="label-disabled">Tx&nbsp;</div>\
                    <input type="checkbox" id="' + type + '-Tx-' + channelId + '" data-channelNo="' + channelId + '"\
                        name="Transmit" value="' + type + '" disabled >';
            }
        }

        html += '</div>';

        return html;
    }

    /**
     * Build the tooltipped titles based on NMEA types.
     * @param {Array[string]} nmeaTypes Array containing NMEA sentences and descriptions.
     * @param {bool} useBaudRow Do we have to make space for the baud rate row?
     */
    BuildTitleGridColumn(nmeaTypes, useBaudRow)
    {
        let html = '\
        <div class="cell outer-cell">\
            <h2>NMEA0183 Sentence</h2>\
        </div>';

        if(useBaudRow)
            html += '\
            <div class="cell outer-cell">\
                <h2>Baud Rate</h2>\
            </div>';

        // Each type has a name and description at index i and i + 1
        // so have to increment i by 2 every loop.
        for(let i = 0; i < nmeaTypes.length; i+=2)
        {
            let title = nmeaTypes[i];
            let desc = nmeaTypes[i + 1];
            html += '<div class="cell outer-cell tooltip-wrapper">\
                        <div class="title">' + title + '\
                        </div>\
                        <div class="tooltip">\
                            <p>' + desc + '</p>\
                        </div>\
                    </div>';
        }
        return html;
    }

    /**
     * Method to build the inner and outer grids of the NMEA filter
     * selection page.
     * @param {*} model - Reference to the MVC model.
     * @param {bool} isPropGrid - Is this the proprietary sentence grid.
     */
    BuildGrid(model, isPropGrid)
    {
         // Channel ID's - restrict channels to match processor
         // Importantly, this prevents the TCP/UDP filter being redrawn for channel 20
        let channelIds = model.channels.filter(channel => ((channel >= 0 && channel <= 19) || channel & (1 << 6)));
        // Array of all NMEA Sentence types and descriptions.
        let nmeaTypes = isPropGrid ? model.NMEAProprietarySentences : model.NMEASentences;

        // Data stored at index specified by channel's id.
        // e.g channel 5 will have all relevent data stored in arrays at [5].
        let baudRates = model.baudRates; // Array of channel's currently selected baud rates.
        let rxFilters = model.NMEARxFilter; // Array of Sets containing enabled Rx Filters.
        let txFilters = model.NMEATxFilter; // Array of Sets containing enabled Tx Filters.
        let portNames = model.NMEANames; // Array containing the channel's name.

        let rows = nmeaTypes.length / 2; // Grid rows.
        let cols = channelIds.length; // Grid cols.

        // Generate outer grid and set css variables.
        let gridClass = isPropGrid ? 'grid prop-outer-grid' : 'grid outer-grid';
        let html = '<div class="' + gridClass + '" style="--gridRows:' + rows + '">';
        html += this.BuildTitleGridColumn(nmeaTypes, !isPropGrid);

        // Generate inner grid and set css variables.
        gridClass = isPropGrid ? 'grid prop-txrx-grid' : 'grid txrx-grid';
        html += '<div class="overflow" style="--gridRows:' + rows + '">';
        html += '<div class="' + gridClass + '" style="--gridRows:' + rows + '; --gridCols:' + cols + '">';
        html += this.BuildPortRow(channelIds, portNames);
        if(!isPropGrid)
            html += this.BuildBaudRateRow(channelIds, baudRates);
        for(let i = 0; i < nmeaTypes.length; i+=2)
            html += this.BuildTxRxRow(channelIds, nmeaTypes[i], rxFilters, txFilters);

        // Close any open tags.
        html += '       </div>\
                    </div>\
                </div>';
        return html;
    }

    update(model)
    {
        /** Build the table's HTML */
        let filterHtml = this.BuildGrid(model, false);
        let proprietaryHtml = this.BuildGrid(model, true);

        // Set the html of the data tables.
        $(".nmea-filter").html(filterHtml);
        $(".nmea-proprietary-filter").html(proprietaryHtml);
    }
}