/**
 * Model, View, Controller for B&G page.
 * 
 * Handles proprietary B&G functions
 * 
 * @category    Webserver
 * @package     ATProcessor
 * @author      Sam Meredith <sam@aandtinstruments.com>
 * @version     0.1
 */

const PROGRESSBAR_MAX = 390;

//----------------------------------------
// Model
//----------------------------------------
class BGModel extends ObservableModel {
    constructor() {
        super();

        this.canSources = {};

        this.init();
    }

    init() {
        let deferred = new $.Deferred();
        let self = this;

        // Get the list of CAN heading sources
        readSingle("CanSource", "Heading").done(function(sourceList) {
            let async = [];

            sourceList.split(';').forEach(function(source) {
                // Load each source
                async.push(readSection("CanDevices:" + source).done(function(sectionJSON) {
                    let section = JSON.parse(sectionJSON);
                    if (!$.isEmptyObject(section))
                        self.canSources[source] = section;
                }));
            });

            $.when.apply($, async).then(function() {
                deferred.resolve();
                self.notifyAll();
            })
        });
        
        return deferred.promise();
    }
}

//----------------------------------------
// Controller
//----------------------------------------
class BGController extends BasicController {
    constructor(model) {
        super(model);
    }

    openModal(e) {
        let canAddress = $('#compass-select option:selected').attr('data-address');

        // Display Modal
        $('#compass-swing-modal').show();

        // Update status fields
        $('#swing-status-container .field-container').attr('data-instance', canAddress);
        $(document).trigger('fields-changed');
    }

    resetModal(e) {
        //Reset progress bar
        $('#progress-bar').progressbar({
            max: PROGRESSBAR_MAX,
            value: 0
        }).show();
        $('#progress-complete').hide();
    }

    startCompassSwing(e) {
        let canAddress = $('#compass-select option:selected').attr('data-address');
        let view = this; // View should be passed as context on bind

        //Reset progress bar
        $('#progress-bar').progressbar({
            max: PROGRESSBAR_MAX,
            value: 0
        }).show();
        $('#progress-complete').hide();

        //Send start to processor
        $.ajax({
            type: 'POST',
            url: '/helpers.php',
            data: {
                action: 'queryProcessor',
                query: 'bandgcompassswing=start&address=' + canAddress
            },
            success: function(response) {
                console.log('Compass swing started: Processor response - ' + response);
            }
        });

        // Begin polling processor for swing status
        if (this.isPolling === undefined || this.isPolling < 0) {
            this.isPolling = setInterval(function() {
                $.ajax({
                    type: 'POST',
                    url: '/helpers.php',
                    data: {
                        action: 'queryProcessor',
                        query: 'fieldId=0x6101,0x6102&senderId=Canbus&senderInstance=' + canAddress
                    },
                    success: function(response) {
                        var fieldMatchRegex = /(0x.*)=\s?(.*)\r/g;
                        var match = null;
                        var parseFields = {};
                        
                        while ((match = fieldMatchRegex.exec(response)) !== null) {
                            parseFields[match[1]] = match[2];
                        }

                        switch (parseFields['0x6101'].toLowerCase()) {
                            case 'failed':
                                view.updateProgress(null, -1);
                                clearInterval(view.isPolling);
                                view.isPolling = -1;
                                break;
                            case 'stopped':
                                view.updateProgress(null, -2);
                                clearInterval(view.isPolling);
                                view.isPolling = -1;
                                break;
                            case 'timed out':
                                view.updateProgress(null, -3);
                                clearInterval(view.isPolling);
                                view.isPolling = -1;
                                break;
                            case 'completed ok':
                                view.updateProgress(null, 1);
                                clearInterval(view.isPolling);
                                view.isPolling = -1;
                                break;
                            case 'started':
                            default:
                                view.updateProgress(Math.abs(parseInt(parseFields['0x6102'])), 0);
                                break;
                        }
                    }
                });
            }, 1000);
        }
    }

    stopCompassSwing(e) {
        let canAddress = $('#compass-select option:selected').attr('data-address');

        $.ajax({
            type: 'POST',
            url: '/helpers.php',
            data: {
                action: 'queryProcessor',
                query: 'bandgcompassswing=stop&address=' + canAddress
            },
            success: function(response) {
                console.log('Compass swing stopped: Processor response - ' + response);
            }
        });

        this.updateProgress(null, 0);
    }
}

//----------------------------------------
// View
//----------------------------------------
class BGView extends BasicView {
    constructor(controller) {
        super(controller);
    }

    bindEvents() {
        super.bindEvents();
        // View passed as context deliberately
        $('#start-swing').on('click', this.controller.startCompassSwing.bind(this));
        $('#stop-swing').on('click', this.controller.stopCompassSwing.bind(this));
        $('#compass-swing').on('click', this.controller.openModal.bind(this));
        $('#compass-select').on('change', this.controller.resetModal.bind(this));
    }

    update(model) {
        // Populate compasses
        if (Object.keys(model.canSources).length > 0) {
            $('#compass-select').empty();
            Object.keys(model.canSources).forEach(function(device) {
                let deviceData = model.canSources[device];
                $('#compass-select').append(
                        '<option value="' + device + '" data-address="' + deviceData.address + '">'
                    +       device + ' - ' + deviceData.serialnumber
                    +   '</option>'
                );
            });
        }

        //Init progress bar
        $('#progress-bar').progressbar({
            max: PROGRESSBAR_MAX,
            value: 0
        }).show();
    }

    updateProgress(progress, status) {

        switch (status) {
            case -3:
                // Swing Timed Out
                $('#progress-bar').progressbar('value', 0);
                $('#progress-complete').text('Compass Swing Timed Out.');
                $('#progress-complete').css('color', '#000');
                $('#progress-complete').show();
                break;
            case -2:
                // Swing stopped
                $('#progress-bar').progressbar('value', 0);
                $('#progress-complete').text('Compass Swing Stopped.');
                $('#progress-complete').css('color', '#000');
                $('#progress-complete').show();
                break;
            case -1:
                // Swing failed
                $('#progress-bar').progressbar('value', 0);
                $('#progress-complete').text('Compass Swing Failed.');
                $('#progress-complete').css('color', '#000');
                $('#progress-complete').show();
                break;
            case 1:
                // Swing complete
                $('#progress-bar').progressbar('value', PROGRESSBAR_MAX);
                $('#progress-complete').text('Compass Swing Complete.');
                $('#progress-complete').css('color', '#fff');
                $('#progress-complete').show();
                break;
            case 0:
            default:
                if (progress !== null)
                    $('#progress-bar').progressbar('value', progress);
                else {
                    $('#progress-bar').progressbar('value', 0);
                    $('#progress-complete').text('Compass Swing Stopped.');
                    $('#progress-complete').css('color', '#000');
                    $('#progress-complete').show();
                }
                break;
        }
    }
}
