define([
    'jquery',
    'bitbucket/internal/model/page-state',
    'bitbucket/internal/model/stash-user',
    'bitbucket/internal/util/ajax',
    'bitbucket/internal/util/events',
    'bitbucket/internal/widget/approve'
], function(
    $,
    pageState,
    StashUser,
    ajax,
    events,
    Approve
) {

    'use strict';

    var ajaxRestHandler;

    module('widget-approve', {
        setup: function () {
            var user = new StashUser({
                name: 'seb',
                displayName: 'Seb Ruiz',
                emailAddress: 'sruiz@atlassian.com',
                avatarUrl: ''
            });
            sinon.stub(pageState, "getCurrentUser", function() {
                return user;
            });
            sinon.stub(pageState, "getPullRequest", function () {
                return {
                    getId: function () {
                        return 1;
                    }
                };
            });
            sinon.stub(ajax, "rest", function () {
                return ajaxRestHandler.apply(this, arguments);
            });


            var triggerHtml = aui.buttons.button({
                iconClass: 'approve-icon',
                extraClasses: 'approve',
                buttonText: 'Approve'
            });

            this.$approveTrigger = $(triggerHtml).appendTo("#qunit-fixture");
        },
        teardown: function () {
            pageState.getCurrentUser.restore();
            pageState.getPullRequest.restore();
            ajax.rest.restore();
            this.$approveTrigger.remove();
        }
    });

    test('approve trigger state is correct', function () {
        var approve = new Approve(this.$approveTrigger, {
        });

        equal(approve.isTriggerActive(), false, 'Approve is not active');
        equal(approve.isTriggerDisabled(), false, 'Approve is not disabled');

        approve.setTriggerActive(true);
        equal(approve.isTriggerActive(), true, 'Approve is active');
        approve.setTriggerDisabled(true);
        equal(approve.isTriggerDisabled(), true, 'Approve is disabled');

        approve.setTriggerActive(false);
        equal(approve.isTriggerActive(), false, 'Approve is not active');

        approve.setTriggerDisabled(false);
        equal(approve.isTriggerDisabled(), false, 'Approve is not disabled');
    });

    test('triggering inactive approve adds approval', function() {

        var approve = new Approve(this.$approveTrigger);

        approve.setTriggerActive(false); // indicates that approve is set

        var eventData = null;
        var removedEventCalled = false;
        var addedEventCalled = false;
        var addingEventCalled = false;
        var removingEventCalled = false;
        var addFailedEventCalled = false;
        var removeFailedEventCalled = false;

        events.on('bitbucket.internal.widget.approve-button.added', function(data) {
            eventData = data;
            addedEventCalled = true;
        });
        events.on('bitbucket.internal.widget.approve-button.removed', function(data) {
            removedEventCalled = true;
        });
        events.on('bitbucket.internal.widget.approve-button.removing', function(data) {
            removingEventCalled = true;
        });
        events.on('bitbucket.internal.widget.approve-button.adding', function(data) {
            addingEventCalled = true;
        });
        events.on('bitbucket.internal.widget.approve-button.remove.failed', function(data) {
            removeFailedEventCalled = true;
        });
        events.on('bitbucket.internal.widget.approve-button.add.failed', function(data) {
            addFailedEventCalled = true;
        });

        ajaxRestHandler = function () {
            return $.Deferred().resolve([{
                user : pageState.getCurrentUser(),
                role : 'REVIEWER',
                approved: false
            }]);
        };

        approve.triggerClicked({
            stopPropagation: $.noop
        });

        equal(addedEventCalled, true, 'added event should have been called');
        equal(removedEventCalled, false, 'removed event should not have been called');
        equal(addingEventCalled, true, 'adding event should have been called');
        equal(removingEventCalled, false, 'removing event should not have been called');
        equal(addFailedEventCalled, false, 'add failed event should not have been called');
        equal(removeFailedEventCalled, false, 'remove failed event should not have been called');
        ok(eventData, 'Event fired when adding approval.');
        equal(eventData.pullRequestId, pageState.getPullRequest().getId(), 'Pull request id is on event data');
        equal(eventData.user.name, pageState.getCurrentUser().getName(), 'Pull request user is on event data');
        equal(eventData.approved, true, 'Participant approval is on event data');
    });

    test('triggering active approve removes approval', function() {

        var approve = new Approve(this.$approveTrigger);

        approve.setTriggerActive(true); // indicates that approve is set

        var eventData = null;
        var removedEventCalled = false;
        var addedEventCalled = false;
        var addingEventCalled = false;
        var removingEventCalled = false;
        var addFailedEventCalled = false;
        var removeFailedEventCalled = false;

        events.on('bitbucket.internal.widget.approve-button.removed', function(data) {
            eventData = data;
            removedEventCalled = true;
        });
        events.on('bitbucket.internal.widget.approve-button.added', function(data) {
            addedEventCalled = true;
        });
        events.on('bitbucket.internal.widget.approve-button.removing', function(data) {
            removingEventCalled = true;
        });
        events.on('bitbucket.internal.widget.approve-button.adding', function(data) {
            addingEventCalled = true;
        });
        events.on('bitbucket.internal.widget.approve-button.remove.failed', function(data) {
            removeFailedEventCalled = true;
        });
        events.on('bitbucket.internal.widget.approve-button.add.failed', function(data) {
            addFailedEventCalled = true;
        });

        ajaxRestHandler = function () {
            return $.Deferred().resolve([{
                user : pageState.getCurrentUser(),
                role : 'REVIEWER',
                approved: false
            }]);
        };

        approve.triggerClicked({
            stopPropagation: $.noop
        });

        equal(removedEventCalled, true, 'removed event should have been called');
        equal(addedEventCalled, false, 'added event should not have been called');
        equal(addingEventCalled, false, 'adding event should not have been called');
        equal(removingEventCalled, true, 'removing event should have been called');
        equal(addFailedEventCalled, false, 'add failed event should not have been called');
        equal(removeFailedEventCalled, false, 'remove failed event should not have been called');
        ok(eventData, 'Event fired when removing approval.');
        equal(eventData.pullRequestId, pageState.getPullRequest().getId(), 'Pull request id is on event data');
        equal(eventData.user.name, pageState.getCurrentUser().getName(), 'Pull request user is on event data');
        equal(eventData.approved, false, 'Participant approval is on event data');
    });

    test('failing approve add fires failure events', function() {

        var approve = new Approve(this.$approveTrigger);

        approve.setTriggerActive(false); // indicates that approve is not set

        var eventData = null;
        var removedEventCalled = false;
        var addedEventCalled = false;
        var addingEventCalled = false;
        var removingEventCalled = false;
        var addFailedEventCalled = false;
        var removeFailedEventCalled = false;

        events.on('bitbucket.internal.widget.approve-button.removed', function(data) {
            removedEventCalled = true;
        });
        events.on('bitbucket.internal.widget.approve-button.added', function(data) {
            addedEventCalled = true;
        });
        events.on('bitbucket.internal.widget.approve-button.removing', function(data) {
            removingEventCalled = true;
        });
        events.on('bitbucket.internal.widget.approve-button.adding', function(data) {
            addingEventCalled = true;
        });
        events.on('bitbucket.internal.widget.approve-button.remove.failed', function(data) {
            removeFailedEventCalled = true;
        });
        events.on('bitbucket.internal.widget.approve-button.add.failed', function(data) {
            eventData = data;
            addFailedEventCalled = true;
        });

        ajaxRestHandler = function () {
            return jQuery.Deferred().reject([{
                user : pageState.getCurrentUser(),
                role : 'REVIEWER',
                approved: false
            }]);
        };

        approve.triggerClicked({
            stopPropagation: jQuery.noop
        });

        equal(addedEventCalled, false, 'added event should not have been called');
        equal(removedEventCalled, false, 'removed event should not have been called');
        equal(addingEventCalled, true, 'adding event should have been called');
        equal(removingEventCalled, false, 'removing event should not have been called');
        equal(addFailedEventCalled, true, 'add failed event should have been called');
        equal(removeFailedEventCalled, false, 'remove failed event should not have been called');
        ok(eventData, 'Event fired when removing approval.');
        equal(eventData.pullRequestId, pageState.getPullRequest().getId(), 'Pull request id is on event data');
        equal(eventData.user.name, pageState.getCurrentUser().getName(), 'Pull request user is on event data');
        equal(eventData.approved, false, 'Participant approval is on event data');
    });

    test('failing approve removal fires failure events', function() {

        var approve = new Approve(this.$approveTrigger);

        approve.setTriggerActive(true); // indicates that approve is set

        var eventData = null;
        var removedEventCalled = false;
        var addedEventCalled = false;
        var addingEventCalled = false;
        var removingEventCalled = false;
        var addFailedEventCalled = false;
        var removeFailedEventCalled = false;

        events.on('bitbucket.internal.widget.approve-button.removed', function(data) {
            removedEventCalled = true;
        });
        events.on('bitbucket.internal.widget.approve-button.added', function(data) {
            addedEventCalled = true;
        });
        events.on('bitbucket.internal.widget.approve-button.removing', function(data) {
            removingEventCalled = true;
        });
        events.on('bitbucket.internal.widget.approve-button.adding', function(data) {
            addingEventCalled = true;
        });
        events.on('bitbucket.internal.widget.approve-button.remove.failed', function(data) {
            eventData = data;
            removeFailedEventCalled = true;
        });
        events.on('bitbucket.internal.widget.approve-button.add.failed', function(data) {
            addFailedEventCalled = true;
        });

        ajaxRestHandler = function () {
            return $.Deferred().reject([{
                user : pageState.getCurrentUser(),
                role : 'REVIEWER',
                approved: false
            }]);
        };

        approve.triggerClicked({
            stopPropagation: $.noop
        });

        equal(addedEventCalled, false, 'added event should not have been called');
        equal(removedEventCalled, false, 'removed event should not have been called');
        equal(addingEventCalled, false, 'adding event should not have been called');
        equal(removingEventCalled, true, 'removing event should have been called');
        equal(addFailedEventCalled, false, 'add failed event should not have been called');
        equal(removeFailedEventCalled, true, 'remove failed event should have been called');
        ok(eventData, 'Event fired when removing approval.');
        equal(eventData.pullRequestId, pageState.getPullRequest().getId(), 'Pull request id is on event data');
        equal(eventData.user.name, pageState.getCurrentUser().getName(), 'Pull request user is on event data');
        equal(eventData.approved, true, 'Participant approval is on event data');
    });
});
