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

 const headingSourcePrefix = "HeadingSource";

 /**
 * Defines compass calibrations
 */
class CompassCorrectionModel extends ObservableModel {
    constructor(sensorNumber) {
        super();

        this.sensorSource = headingSourcePrefix + (sensorNumber || 0);
    }

    //----------------------------------------
    // Getters/Setters
    //----------------------------------------
    get useHeelCorrections() {
        return this.data.heelcorrection;
    }
    set useHeelCorrections(enabled) {
        this.data.heelcorrection = enabled;
    }

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

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

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

    get sender() {
        return this.data.source;
    }

    init() {
        let self = this;
        let defaults = {
            "heelcorrection" : false,
            "heeloffset.-15" : "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0",
            "heeloffset.-10" : "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0",
            "heeloffset.-5" : "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0",
            "heeloffset.0" : "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0",
            "heeloffset.5" : "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0",
            "heeloffset.10" : "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0",
            "heeloffset.15" : "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0",
            "offset": "0.0",
            "instance": "0",
            "source": "No Source"
        }

      readSection(self.sensorSource).done(function(sensorSource) {
           self.data = $.extend({}, defaults, JSON.parse(sensorSource));

            let async = [];

           if (self.sender.toLowerCase() == "canbus") {
                // Need to grab the CANbus instance
                let def = new $.Deferred();
                async.push(def.promise());
                let sensorNumber = self.sensorSource.slice(headingSourcePrefix.length);
                readSingle(headingSourcePrefix + sensorNumber, "uniqueid").done(function(headingSourceId) {
                    readSingle("CanDevices:" + headingSourceId, "Address").done(function(address) {
                        self.instance = address;
                        def.resolve();
                    });
                });
           }

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

    persistData() {
        let self = this;
        let databaseArray = [];

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

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

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

    changeCorrection(e) {
        validateRange($(e.target), 1, -20, 20, 0);

        let key = "heeloffset." + $(e.target).attr('data-heel');

        let offsetArray = this.model.data[key].split(',');
        offsetArray[$(e.target).attr('data-index')] = $(e.target).val();
        this.model.data[key] = offsetArray.join(',');
    }

    toggleHeelCorrections(e) {
        this.model.useHeelCorrections = $(e.target).is(':checked');
    }
}

/**
 * Handle display for compass correction page
 */
class CompassCorrectionView extends BasicView {
    constructor(controller) {
        super(controller);

        this.controller.model.init();
    }

    bindEvents() {
        super.bindEvents();

        $('#compass-correction-container').on('change', this.controller.changeCorrection.bind(this.controller));
        $('#heel-correction').on('change', this.controller.toggleHeelCorrections.bind(this.controller));
    }

    drawCorrectionTable(model) {
        $('#compass-correction-container').append(
                '<h2>Compass</h2>'
            +   '<h2>0&deg;</h2>'
            +   '<h2>20&deg;</h2>'
            +   '<h2>40&deg;</h2>'
            +   '<h2>60&deg;</h2>'
            +   '<h2>80&deg;</h2>'
            +   '<h2>100&deg;</h2>'
            +   '<h2>120&deg;</h2>'
            +   '<h2>140&deg;</h2>'
            +   '<h2>160&deg;</h2>'
            +   '<h2>180&deg;</h2>'
            +   '<h2>200&deg;</h2>'
            +   '<h2>220&deg;</h2>'
            +   '<h2>240&deg;</h2>'
            +   '<h2>260&deg;</h2>'
            +   '<h2>280&deg;</h2>'
            +   '<h2>300&deg;</h2>'
            +   '<h2>320&deg;</h2>'
            +   '<h2>340&deg;</h2>'
            +   '<h2>360&deg;</h2>'
            +   '<h2 id="heel-row">Heel</h2>'
            +   '<h2></h2>'
            +   '<h2></h2>'
            +   '<h2></h2>'
            +   '<h2></h2>'
            +   '<h2></h2>'
            +   '<h2></h2>'
            +   '<h2></h2>'
            +   '<h2></h2>'
            +   '<h2></h2>'
            +   '<h2></h2>'
            +   '<h2></h2>'
            +   '<h2></h2>'
            +   '<h2></h2>'
            +   '<h2></h2>'
            +   '<h2></h2>'
            +   '<h2></h2>'
            +   '<h2></h2>'
            +   '<h2></h2>'
            +   '<h2></h2>'
        );

        $('#compass-correction-container').append('<h2>-15&deg;</h2>');
        model.data["heeloffset.-15"].split(",").forEach(function(value, index) {
            $('#compass-correction-container').append(
                '<input type="number" step="0.1" value="' + value + '" data-heel="-15" data-index="' + index + '">'
            );
        });

        $('#compass-correction-container').append('<h2>-10&deg;</h2>');
        model.data["heeloffset.-10"].split(",").forEach(function(value, index) {
            $('#compass-correction-container').append(
                '<input type="number" step="0.1" value="' + value + '" data-heel="-10" data-index="' + index + '">'
            );
        });

        $('#compass-correction-container').append('<h2>-5&deg;</h2>');
        model.data["heeloffset.-5"].split(",").forEach(function(value, index) {
            $('#compass-correction-container').append(
                '<input type="number" step="0.1" value="' + value + '" data-heel="-5" data-index="' + index + '">'
            );
        });

        $('#compass-correction-container').append('<h2>0&deg;</h2>');
        model.data["heeloffset.0"].split(",").forEach(function(value, index) {
            $('#compass-correction-container').append(
                '<input type="number" step="0.1" value="' + value + '" data-heel="0" data-index="' + index + '">'
            );
        });

        $('#compass-correction-container').append('<h2>5&deg;</h2>');
        model.data["heeloffset.5"].split(",").forEach(function(value, index) {
            $('#compass-correction-container').append(
                '<input type="number" step="0.1" value="' + value + '" data-heel="5" data-index="' + index + '">'
            );
        });

        $('#compass-correction-container').append('<h2>10&deg;</h2>');
        model.data["heeloffset.10"].split(",").forEach(function(value, index) {
            $('#compass-correction-container').append(
                '<input type="number" step="0.1" value="' + value + '" data-heel="10" data-index="' + index + '">'
            );
        });

        $('#compass-correction-container').append('<h2>15&deg;</h2>');
        model.data["heeloffset.15"].split(",").forEach(function(value, index) {
            $('#compass-correction-container').append(
                '<input type="number" step="0.1" value="' + value + '" data-heel="15" data-index="' + index + '">'
            );
        });
    }

    update(model) {
        $('#heel-correction').prop('checked', model.useHeelCorrections);
        $('#fixed-offset').val(model.offset);

        $('#raw-compass-true').attr('data-sender', model.sender);
        $('#raw-compass-true').attr('data-instance', model.instance);
        $('#raw-compass-mag').attr('data-sender', model.sender);
        $('#raw-compass-mag').attr('data-instance', model.instance);

        $('.page-title > h1').text('Compass Calibration - ' + (model.name || 'Heading ' + (parseInt(model.sensorSource.slice(-1)) + 1)))

        $('#compass-correction-container').empty();
        this.drawCorrectionTable(model);
    }
}