/*
 * ValidationPanel is a class that abstracts the message, vertex 
 * and exception details. It has three view modes - compact, preview and expanded.
 * @param {container, resizeCallback} options - Initialize panel with these options.
 * @param options.validationPanelContainer - Container of the panel.
 * @param {callback} options.resizeCallback - Called when manual resize of the panel is complete.
 * @param {object} options.editor - Reference to the graph editor object.
 */
function ValidationPanel(options) {
    // JSON object of the buttons appearing.
    // The key, i.e. M, E, V are used in the compact mode
    this.buttonData = {
        'M' : {
            fullName : 'Message Integrity',
            clickHandler : this.showMessageViolations.bind(this)
        },
        'E' : {
            fullName : 'Exceptions',
            clickHandler : this.showExceptions.bind(this)
        },
        'V' : {
            fullName : 'Vertex Integrity',
            clickHandler : this.showVertexViolations.bind(this)
        }
    }

    // Both in px
    this.compactWidth = 60;
    this.previewWidth = 170;
    // This is in %
    this.expandWidth = 55;
    this.state = ValidationPanel.StateEnum.COMPACT;
    this.container = options.container;
    this.resizeCallback = options.resizeCallback;
    this.debuggerServerRoot = options.debuggerServerRoot;
    this.editor = options.editor;
    // Which label is currently being shown
    this.currentLabel = null;
    
    $(this.container).css('height', this.height + 'px')
    // Make it resizable horizontally
    $(this.container).resizable({ handles : 'e', minWidth : this.previewWidth,
        stop: (function(event, ui) {
            this.resizeCallback();
        }).bind(this)
    });
    this.initElements();
    this.compact();
}

ValidationPanel.StateEnum = {
    COMPACT : 'compact',
    PREVIEW : 'preview',
    EXPAND : 'expand'
}

/*
 * Deferred callbacks for capture scenario
 */
ValidationPanel.prototype.onCaptureVertex = function(done, fail) {
    this.onCaptureVertex.done = done;
    this.onCaptureVertex.fail = fail;
}

/*
 * Creates HTML elements for valpanel.
 */
ValidationPanel.prototype.initElements = function() {
    // Div to host the right arrow and close button on the top right.
    var iconsContainer = $('<div />')
                            .attr('class', 'valpanel-icons-container')
                            .appendTo(this.container)

    // Create a right-pointed arrow
    this.rightArrow = $('<span />')
        .attr('class', 'glyphicon glyphicon-circle-arrow-right')
        .appendTo(iconsContainer);

    // Create a close button - Clicking it will compact the panel.
    this.btnClose = $('<span />')
        .attr('class', 'glyphicon glyphicon-remove valpanel-btn-close')
        .click((function() { 
            this.compact(); 
        }).bind(this))
        .hide()
        .appendTo(iconsContainer);

    // Create all the buttons.
    this.btnContainer = $('<ul />')
        .attr('class', 'list-unstyled valpanel-btn-container')    
        .appendTo(this.container);

    // This is the container for the main content.
    this.contentContainer = $('<div />')
        .attr('class', 'valpanel-content-container')
        .hide()
        .appendTo(this.container);

    // Preloader reference.
    this.preloader = $('<div />')
        .attr('class', 'valpanel-preloader')
        .hide()
        .appendTo(this.container);

    for (var label in this.buttonData) {
        var button = $('<button />')
                        .attr('class', 'btn btn-success btn-valpanel')
                        .attr('id', this.btnLabelToId(label))
                        .attr('disabled', 'true')
                        .click(this.buttonData[label]['clickHandler']);
        var iconSpan = $('<span />')
            .appendTo(button);
        var textSpan = $("<span />")
            .html(' ' + label)
            .appendTo(button);
        // Associate this physical button element with the cache entry.
        this.buttonData[label].button = button;
        this.buttonData[label].iconSpan = iconSpan;
        this.buttonData[label].textSpan = textSpan;
        $(this.btnContainer).append(
            $("<li />").append(button)
        );
    }
}

ValidationPanel.prototype.btnLabelToId = function(label) {
    return 'btn-valpanel-' + label;
}

/*
 * Expands the width of the panel to show full names of each of the buttons.
 */
ValidationPanel.prototype.preview = function() {
    if (!$(this.container).is(':animated')) {
        // Set state to preview.
        this.btnContainer.removeClass(this.state);
        this.state = ValidationPanel.StateEnum.PREVIEW;
        this.btnContainer.addClass(this.state);
        $(this.btnClose).hide();
        $(this.contentContainer).hide();
        $(this.container).animate({ width: this.previewWidth + 'px'}, 300, 
            (function() { 
                this.resizeCallback(); 
        }).bind(this));

        // Expand names to full names 
        for (var label in this.buttonData) {
            var buttonData = this.buttonData[label];
            $(buttonData.textSpan).html(buttonData.fullName);
        }
    }
}

/*
 * Compacts the width of the panel to show only the labels of the buttons.
 */
ValidationPanel.prototype.compact = function() {
    if (!$(this.container).is(':animated')) {
        var prevState = this.state;
        this.currentLabel = null;
        this.state = ValidationPanel.StateEnum.COMPACT;
        // Uncolor all editor nodes
        this.editor.colorNodes([], null /* not required */, true);
        $(this.btnClose).hide();
        $(this.rightArrow).show();
        $(this.contentContainer).hide();
        $(this.container).animate({ width: this.compactWidth + 'px'}, 300,
            (function() {
                // Compact names to labels.
                for (var label in this.buttonData) {
                    var buttonData = this.buttonData[label];
                    $(buttonData.textSpan).html(label);
                }    
                this.btnContainer.removeClass(prevState);
                this.btnContainer.addClass(this.state);
                this.resizeCallback(); 
        }).bind(this));
    }
}

ValidationPanel.prototype.expand = function() {
    this.btnContainer.removeClass(this.state);
    this.state = ValidationPanel.StateEnum.EXPAND;
    this.btnContainer.addClass(this.state);
    // Show close button, hide right arrow, show content.
    $(this.btnClose).show();
    $(this.rightArrow).hide();
    $(this.container).animate({ width: this.expandWidth + '%'}, 500,
        (function() {
            $(this.contentContainer).show('slow');
            this.resizeCallback();
        }).bind(this));
}

/*
 * Fetch the message integrity violations from the debugger server
 * and construct a table to show the data.
 */
ValidationPanel.prototype.showMessageViolations = function() {
    this.expand();
    this.currentLabel = 'M';
    // Empty the content container and add violations table.
    this.contentContainer.empty();
    // The data should already be present in the buttonData cache.
    var data = this.buttonData[this.currentLabel].data;
    var table = $("<table />")
        .attr('class', 'table')
        .attr('id', 'valpanel-M-table')
        .html('<thead><tr><th>Source ID</th><th>Destination ID</th><th>Message</th><th></th></tr></thead>')
        .appendTo(this.contentContainer);

    var btnCaptureScenario = 
        $('<button type="button" class="btn btn-sm btn-primary btn-vp-M-capture">Capture Scenario</button>');

    var dataTable = $(table).DataTable({
        'columns' : [
            { 'data' : 'srcId' },
            { 'data' : 'destinationId' },
            { 'data' : 'message' },
            {
                'orderable' : false,
                'data' : null,
                'defaultContent' : $(btnCaptureScenario).prop('outerHTML')
            },
        ]
    });
    if (data) {
        for (var taskId in data) {
            var violations = data[taskId].violations;
            for (var i = 0; violations && i < violations.length; ++i) {
                var violation = violations[i];
                violation.superstepId = this.superstepId;
                dataTable.row.add(violation).draw();
            }
        }
    }
    // Attach click event to the capture Scenario button.
    $('button.btn-vp-M-capture').click((function(event) {
        var tr = $(event.target).parents('tr');
        var row = dataTable.row(tr);
        var data = row.data();
        Utils.fetchVertexTest(this.debuggerServerRoot, this.jobId, 
            this.superstepId, data.srcId, 'msg')
        .done((function(response) {
            this.onCaptureVertex.done(response);
        }).bind(this))
        .fail((function(response) {
            this.onCaptureVertex.fail(response.responseText);
        }).bind(this))
    }).bind(this));
}

/*
 * Fetch vertex value violations from the server and
 * construct a table to show the data.
 */
ValidationPanel.prototype.showVertexViolations = function() {
    this.expand();
    this.currentLabel = 'V';
    var data = this.buttonData[this.currentLabel].data;
    // Empty the content container and add violations table.
    this.contentContainer.empty();
    var table = $("<table />")
        .attr('class', 'table')
        .attr('id', 'valpanel-V-table')
        .html('<thead><tr><th>Vertex ID</th><th>Vertex Value</th><th></th></tr></thead>')
        .appendTo(this.contentContainer);

    var btnCaptureScenario = 
        $('<button type="button" class="btn btn-sm btn-primary btn-vp-V-capture">Capture Scenario</button>');

    var dataTable = $(table).DataTable({
        'columns' : [
            { 'data' : 'vertexId' },
            { 'data' : 'vertexValue' },
            {
                'orderable' : false,
                'data' : null,
                'defaultContent' : $(btnCaptureScenario).prop('outerHTML')
            },
        ]
    });
    var violationIds = [];
    if (data) {
        for (var vertexId in data) {
            var violation = data[vertexId];
            violation.superstepId = this.superstepId;
            dataTable.row.add(violation).draw();
            violationIds.push(vertexId);
        }
    }
    // Attach click event to the capture Scenario button.
    $('button.btn-vp-V-capture').click((function(event) {
        var tr = $(event.target).parents('tr');
        var row = dataTable.row(tr);
        var data = row.data(); 
        Utils.fetchVertexTest(this.debuggerServerRoot, this.jobId, 
            this.superstepId, data.vertexId, 'vv')
        .done((function(response) {
            this.onCaptureVertex.done(response);
        }).bind(this))
        .fail((function(response) {
            this.onCaptureVertex.fail(response.responseText);
        }).bind(this))
    }).bind(this));
    // Color the vertices with violations
    this.editor.colorNodes(violationIds, this.editor.errorColor, true);
}

/*
 * Show exceptions for this superstep.
 */
ValidationPanel.prototype.showExceptions = function() {
    this.expand();
    this.currentLabel = 'E';
    var data = this.buttonData[this.currentLabel].data;
    // Empty the content container and add violations table.
    // TODO(vikesh) Master exceptions.
    this.contentContainer.empty();
    var table = $("<table />")
        .attr('class', 'table')
        .attr('id', 'valpanel-V-table')
        .html('<thead><tr><th>Vertex ID</th><th>Message</th><th>Stack Trace</th><th></th></tr></thead>')
        .appendTo(this.contentContainer);

    var btnCaptureScenario = 
        $('<button type="button" class="btn btn-sm btn-primary btn-vp-E-capture">Capture Scenario</button>');

    var dataTable = $(table).DataTable({
        'columns' : [
            { 'data' : 'vertexId' },
            { 'data' : 'exception.message' },
            { 'data' : 'exception.stackTrace' },
            {
                'orderable' : false,
                'data' : null,
                'defaultContent' : $(btnCaptureScenario).prop('outerHTML')
            }
        ]
    });
    var violationIds = [];
    if (data) {
        for (var vertexId in data) {
            var violation = data[vertexId];
            violation.superstepId = this.superstepId;
            dataTable.row.add(violation).draw();
            violationIds.push(vertexId);
        }
    }
    // Attach click event to the capture Scenario button.
    $('button.btn-vp-E-capture').click((function(event) {
        var tr = $(event.target).parents('tr');
        var row = dataTable.row(tr);
        var data = row.data(); 
        Utils.fetchVertexTest(this.debuggerServerRoot, this.jobId, 
            this.superstepId, data.vertexId, 'err')
        .done((function(response) {
            this.onCaptureVertex.done(response);
        }).bind(this))
        .fail((function(response) {
            this.onCaptureVertex.fail(response.responseText);
        }).bind(this))
    }).bind(this));
    // Color the nodes with exception.
    this.editor.colorNodes(violationIds, this.editor.errorColor, true);
}

/*
 * Handle the received data from the debugger server.
 */
ValidationPanel.prototype.onReceiveData = function(buttonType) {
    return (function(response) {
        // Data is set here. The click handlers will simply use this data.
        this.buttonData[buttonType].data = response;
        this.buttonData[buttonType].button.attr('disabled', false);
        // No violations.
        if($.isEmptyObject(response)) {
            this.buttonData[buttonType].button.addClass('btn-success');
            this.buttonData[buttonType].button.removeClass('btn-danger');
        } else {
            this.buttonData[buttonType].button.addClass('btn-danger');
            this.buttonData[buttonType].button.removeClass('btn-success');
        }
        // If this is the currently selected label, update the contents.
        if (buttonType === this.currentLabel) {
            this.buttonData[buttonType].clickHandler(); 
        }
    }).bind(this);
}

/*
 * Sets the current jobId and superstepId. Expected to called by the 
 * orchestrator (debugger.js) while stepping through the job.
 * @param {jobId, superstepId} data
 * @param data.jobId - Current jobId
 * @param data.superstepId - Current superstepId
 */
ValidationPanel.prototype.setData = function(jobId, superstepId) {
    this.jobId = jobId;
    this.superstepId = superstepId;

    // setData makes AJAX calls to the debugger server for each button type
    for (var type in this.buttonData) {
        // Disable all buttons to begin with
        this.buttonData[type].button.attr('disabled', true);
        $.ajax({
                url: this.debuggerServerRoot + '/integrity',
                data: {'jobId' : this.jobId, 'superstepId' : this.superstepId, 'type' : type}
        })
        .retry({
                times: 3,
                timeout: 1000,
        })
        .done(this.onReceiveData(type))
        .fail((function(buttonLabel) {
                return function(response) {
                    noty({text : 'Failed to fetch data for ' + buttonLabel + 
                                '. Please check your network and debugger server.', type : 'error'});
                }
            })(this.buttonData[type].fullName))
        }
}

ValidationPanel.prototype.showPreloader = function() {
    this.preloader.show('slow');
}

ValidationPanel.prototype.hidePreloader = function() {
    this.preloader.hide('slow');
}
