/* global AJS:false */
AJS.test.require([
    'com.atlassian.bitbucket.server.bitbucket-web:bitbucket-participants-data-provider',
    'com.atlassian.bitbucket.server.bitbucket-web:lodash',
    'com.atlassian.bitbucket.server.bitbucket-it-javascript:js-test-utils'
], function() {
    'use strict';

    var testContext = require('test-context');
    var _ = require('lodash');

    var ParticipantsDataProvider = require('bitbucket/internal/impl/data-provider/participants');

    QUnit.module('participants-data-provider', {
        beforeEach: function() {
            var project1 = { key: 'PROJECT_1' };
            this.fork = {
                project: project1,
                name: 'participants-test',
                slug: 'participants-test'
            };
            this.author = {
                name: "test-participant-author",
                password: "test-participant-author",
                displayName: "test-participant-author",
                emailAddress: "test-participant-author@example.com"
            };
            this.reviewer = {
                name: "test-participant-reviewer",
                password: "test-participant-reviewer",
                displayName: "test-participant-reviewer",
                emailAddress: "test-participant-reviewer@example.com"
            };
            this.participant = {
                name: "test-participant-participant",
                password: "test-participant-participant",
                displayName: "test-participant-participant",
                emailAddress: "test-participant-participant@example.com"
            };

            this._context = testContext.context();
            this._context.loginAsAdmin();

            this._context.fork({
                project: project1,
                slug: 'rep_1'
            }, this.fork);

            this._context.updateRepo(_.extend({
                'public': true
            }, this.fork));

            [this.author, this.reviewer, this.participant].forEach(function (user) {
                this._context.user(user);
            }, this);

            this._context.logout();
            this._context.login(this.author.name, this.author.password);

            this.pullRequest = this._context.pullRequest(project1.key, this.fork.slug, {
                title: "participants-test",
                fromRef: { id: 'refs/heads/basic_branching' },
                toRef: { id: 'refs/heads/master' },
                reviewers: [
                    {
                        "user": this.reviewer
                    }
                ]
            });

            this._context.logout();

            this._context.login(this.participant.name, this.participant.password);

            this._context.pullRequestComment(project1.key, this.fork.slug, this.pullRequest.id, {
                text: 'Drive by comment'
            });

        },
        afterEach: function() {
            this._context.destroy();
        }
    });

    QUnit.test('Unfiltered request gets all 3', function (assert) {
        var pdp = new ParticipantsDataProvider({
            repository: this.fork,
            filter: {}
        });

        var self = this;
        return pdp.fetchNext().then(function (users) {
            assert.strictEqual(users.length, 3, 'All users were returned');
            assert.strictEqual(pdp.reachedEnd, true, 'Only one page');
            assert.ok(hasUserResult(users, self.author), 'Author was returned as a participant');
            assert.ok(hasUserResult(users, self.reviewer), 'Reviewer was returned as a participant');
            assert.ok(hasUserResult(users, self.participant), 'Participant was returned as a participant');
        });
    });

    QUnit.test('Filtering by name', function (assert) {
        var pdp = new ParticipantsDataProvider({
            repository: this.fork,
            filter: { }
        });

        pdp.setFilter('term', 'author');

        var self = this;
        return pdp.fetchNext().then(function (users) {
            assert.strictEqual(users.length, 1, 'One user is returned');
            assert.strictEqual(pdp.reachedEnd, true, 'Only one page');
            assert.ok(hasUserResult(users, self.author), 'Author was returned as a participant');
        });
    });

    QUnit.test('Filtering by role REVIEWER', function (assert) {
        var pdp = new ParticipantsDataProvider({
            repository: this.fork,
            filter: { }
        });

        pdp.setFilter('role', 'REVIEWER');

        var self = this;
        return pdp.fetchNext().then(function (users) {
            assert.strictEqual(users.length, 1, 'One user is returned');
            assert.strictEqual(pdp.reachedEnd, true, 'Only one page');
            assert.ok(hasUserResult(users, self.reviewer), 'Reviewer was returned as a participant');
        });
    });

    QUnit.test('Filtering by role PARTICIPANT and term', function (assert) {
        var pdp = new ParticipantsDataProvider({
            repository: this.fork,
            filter: { }
        });

        pdp.setFilter('role', 'PARTICIPANT');

        return pdp.fetchNext().then(function (users) {
            assert.strictEqual(users.length, 1, 'One user is returned');
            assert.strictEqual(pdp.reachedEnd, true, 'Only one page');
        });
    });

    function hasUserResult(results, expected) {
        var name = expected.name || expected;
        var found = false;
        results.forEach(function (test) {
            if (test.name ===  name) {
                found = true;
            }
        });
        return found;
    }
});
