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

let MAX_WIND_INPUTS = 2;
let MAX_SPEED_INPUTS = 2;
let MAX_DEPTH_INPUTS = 4;
const MAX_POSITION_INPUTS = 4;
const MAX_HEADING_INPUTS = 4;

 /**
 * Defines ATP settings
 */
class SettingsModel extends ObservableModel 
{
    constructor() 
    {
        super();

        this.data = {};
        this.speedinputschanged = false;
        this.windinputschanged = false;
        this.depthinputschanged = false;
        
        this.headinginputschanged = false;
        this.curDefaultHeadingSource = "HeadingSource0";

        this.positioninputschanged = false;
        this.curDefaultPositionSource = "GpsSource0";
    }

    get numspeedinputs() 
    {
        return parseInt(this.data.speedinputs);
    }
    set numspeedinputs(num) 
    {
        this.data.speedinputs = num;
    }
    get numwindinputs() 
    {
        return parseInt(this.data.windinputs);
    }
    set numwindinputs(num) 
    {
        this.data.windinputs = num;
    }
    get numdepthinputs() 
    {
        return parseInt(this.data.depthinputs)
    }
    set numdepthinputs(num) 
    {
        this.data.depthinputs = num
    }
    get numheadinginputs() 
    {
        return parseInt(this.data.headinginputs);
    }
    set numheadinginputs(num) 
    {
        this.data.headinginputs = num;
    }
    get numpositioninputs() 
    {
        return parseInt(this.data.positioninputs);
    }
    set numpositioninputs(num) 
    {
        this.data.positioninputs = num;
    }

    init()
    {
        let self = this;
        let defaults = {
            speedinputs: "1",
            windinputs: "1",
            depthinputs: "1",
            headinginputs: "1",
            positioninputs: "1"
        }

        let async = [];

        let settings;
        let depthsources;
        let headingsources;
        let positionsources;

        async.push(readSection("Settings").done(function(settingJSON)
        {
            settings = JSON.parse(settingJSON);
        }));

        async.push(readSingle("Depth", "SourceCount").done(function(sourceNo)
        {
            depthsources = { depthinputs: (sourceNo || "1") };
        }));

        async.push(readSingle("Heading", "SourceCount").done(function(sourceNo)
        {
            headingsources = { headinginputs: (sourceNo || "1") };
        }));

        async.push(readSingle("Heading", "Default").done(function(defaultSource)
        {
            if (defaultSource.toLowerCase().startsWith("headingsource"))
                self.curDefaultHeadingSource = defaultSource;
        }));

        async.push(readSingle("GPS", "SourceCount").done(function(sourceNo)
        {
            positionsources = { positioninputs: (sourceNo || "1") };
        }));

        async.push(readSingle("GPS", "Default").done(function(defaultSource)
        {
            if (defaultSource.toLowerCase().startsWith("gpssource"))
                self.curDefaultPositionSource = defaultSource;
        }));

        $.when.apply($, async).then(function()
        {
            $.extend(self.data, defaults, settings, depthsources, headingsources, positionsources);
            self.notifyAll();
        });
    }

    persistData()
    {
        let databaseArray = [];

        databaseArray.push( { 'section' : 'Settings', 'key' : "SpeedInputs", 'value' : this.numspeedinputs } );
        databaseArray.push( { 'section' : 'Settings', 'key' : "WindInputs", 'value' : this.numwindinputs } );
        databaseArray.push( { 'section' : 'Depth', 'key' : "SourceCount", 'value' : this.numdepthinputs } );

        databaseArray.push( { 'section' : 'Heading', 'key' : "SourceCount", 'value' : this.numheadinginputs } );
        databaseArray.push( { 'section' : 'Heading', 'key' : "Default", 'value' : this.curDefaultHeadingSource });
        databaseArray.push( { 'section' : 'GPS', 'key' : "SourceCount", 'value' : this.numpositioninputs } );
        databaseArray.push( { 'section' : 'GPS', 'key' : "Default", 'value' : this.curDefaultPositionSource });

        if (this.speedinputschanged)
        {
            databaseArray.push({ section: 'Speed', key: 'default', value: 'SpeedSource0' });
            databaseArray.push({ section: 'Speed', key: 'switching', value: false });
        }

        if (this.windinputschanged)
        {
            databaseArray.push({ section: 'Wind', key: 'default', value: 'WindSource0' });
            databaseArray.push({ section: 'Wind', key: 'switching', value: false });
        }

        if (this.depthinputschanged)
        {
            databaseArray.push({ section: 'Depth', key: 'default', value: 'DepthSource0' });
            databaseArray.push({ section: 'Depth', key: 'switching', value: false });
        }

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

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

    changeSpeedInputs(e)
    {
        this.model.numspeedinputs = $(e.target).val();

        if (parseInt($(e.target).val()) == 1)
        {
            this.model.speedinputschanged = true;
        } 
        else 
        {
            this.model.speedinputschanged = false;
        }
    }

    changeWindInputs(e)
    {
        this.model.numwindinputs = $(e.target).val();

        if (parseInt($(e.target).val()) == 1) {
            this.model.windinputschanged = true;
        } else {
            this.model.windinputschanged = false;
        }
    }

    changeDepthInputs(e)
    {
        this.model.numdepthinputs = $(e.target).val();

        if (parseInt($(e.target).val()) == 1)
        {
            this.model.depthinputschanged = true;
        } 
        else
        {
            this.model.depthinputschanged = false;
        }
    }

    changeHeadingInputs(e)
    {
        this.model.numheadinginputs = $(e.target).val();

        let currentSource = parseInt(this.model.curDefaultHeadingSource.slice(-1));
        if (isNaN(currentSource) || currentSource > MAX_HEADING_INPUTS) currentSource = MAX_HEADING_INPUTS;
        if (this.model.numheadinginputs <= currentSource)
        {
            this.model.curDefaultHeadingSource = "HeadingSource" + (this.model.numheadinginputs - 1);
        }

        console.log(this.model);
    }

    changePositionInputs(e)
    {
        this.model.numpositioninputs = $(e.target).val();

        let currentSource = parseInt(this.model.curDefaultPositionSource.slice(-1));
        if (isNaN(currentSource) || currentSource > MAX_POSITION_INPUTS) currentSource = MAX_POSITION_INPUTS;
        if (this.model.numpositioninputs <= currentSource)
        {
            this.model.curDefaultPositionSource = "GpsSource" + (this.model.numpositioninputs - 1);
        }
    }

    clickApply(e)
    {
        if (this.model.depthinputschanged || this.model.windinputschanged || this.model.speedinputschanged || 
            this.model.headinginputschanged || this.model.positioninputschanged)
            this.showDialog();
        else
            super.clickApply(e);
    }

    clickOK(e)
    {
        if (this.model.depthinputschanged || this.model.windinputschanged || this.model.speedinputschanged || 
            this.model.headinginputschanged || this.model.positioninputschanged)
            this.showDialog($('#atp-header').find('#' + $(e.target).parents('section').last().attr('data-heading')).attr('href'));
        else
            super.clickOK(e);
    }
    
    // Bring up the warning dialog and redirect if a link is supplied.
    showDialog(link = false)
    {
        let self = this;

        // Reset Dialog
        $('#dialog-text').empty();
        $('#progressBar').hide();

        // Setup dialog
        let dialogText = "";
        
        if (this.model.depthinputschanged || this.model.windinputschanged || this.model.speedinputschanged)
        {
            dialogText += "<strong>Warning</strong>: reducing the number of inputs to 1 will turn off auto-switching. <br><br>";
            dialogText += "The current setting will also ";
        } 
        else
            dialogText += "The current setting will ";

        dialogText += "set the active source as Input 1 for the following input type(s): <br><br>";

        dialogText += this.model.speedinputschanged ? "- Speed<br>" : "";
        dialogText += this.model.depthinputschanged ? "- Depth<br>" : "";
        dialogText += this.model.windinputschanged ? "- Wind<br>" : "";
        dialogText += this.model.headinginputschanged ? "- Heading<br>" : "";
        dialogText +=  this.model.positioninputschanged ?  "- Position<br>" : "";
        dialogText += "<br />Press Ok to continue or Cancel to leave settings as they are.";

        $('#dialog-text').html(dialogText);

        $('#dialog').dialog(
        {
            title: "Are You Sure?",
            buttons:
            {
                Ok: function()
                {
                    self.model.persistData().done( function()
                    {
                        if (link)
                        {
                            window.location.href = link;
                        } 
                        else
                        {
                            self.model.windinputschanged = false;
                            self.model.speedinputschanged = false;
                            self.model.depthinputschanged = false;
                            self.model.headinginputschanged = false;
                            self.model.positioninputschanged = false;
                            $('#dialog').dialog('close');
                        }
                    });
                },
                Cancel: function()
                {
                    $('#dialog').dialog('close');
                    $('#progressBar').hide();
                }
            }
        }).dialog('open');
    }
}

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

        this.controller.model.init();
    }

    bindEvents()
    {
        super.bindEvents();

        $('#speed-number-select').on('change', this.controller.changeSpeedInputs.bind(this.controller));
        $('#wind-number-select').on('change', this.controller.changeWindInputs.bind(this.controller));
        $('#depth-number-select').on('change', this.controller.changeDepthInputs.bind(this.controller));
        $('#position-number-select').on('change', this.controller.changePositionInputs.bind(this.controller));
        $('#heading-number-select').on('change', this.controller.changeHeadingInputs.bind(this.controller));
    }

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

        for (let i = 1; i <= MAX_SPEED_INPUTS; i++)
        {
            $('#speed-number-select').append(
                    '<option value="' + i + '" ' + (i == model.numspeedinputs ? "selected" : "") + '>' + i + '</option>'
            );
        }
        for (let i = 1; i <= MAX_WIND_INPUTS; i++)
        {
            $('#wind-number-select').append(
                    '<option value="' + i + '" ' + (i == model.numwindinputs ? "selected" : "") + '>' + i + '</option>'
            );
        }
        for (let i = 1; i <= MAX_DEPTH_INPUTS; i++)
        {
            $('#depth-number-select').append(
                    '<option value="' + i + '" ' + (i == model.numdepthinputs ? "selected" : "") + '>' + i + '</option>'
            );
        }
        for (let i = 1; i <= MAX_POSITION_INPUTS; i++)
        {
            $('#position-number-select').append(
                    '<option value="' + i + '" ' + (i == model.numpositioninputs ? "selected" : "") + '>' + i + '</option>'
            );
        }
        for (let i = 1; i <= MAX_HEADING_INPUTS; i++)
        {
            $('#heading-number-select').append(
                    '<option value="' + i + '" ' + (i == model.numheadinginputs ? "selected" : "") + '>' + i + '</option>'
            );
        }
    }
}