/* global AJS:false */
AJS.test.require([
    'com.atlassian.bitbucket.server.bitbucket-bbui-components:mirroring-admin',
    'com.atlassian.bitbucket.server.bitbucket-bbui-components:widget',
    'com.atlassian.bitbucket.server.bitbucket-it-javascript:js-test-utils'
], function() {
    var $ = jQuery;
    var MirroringAdminView = require('bitbucket/internal/bbui/mirroring-admin/mirroring-admin');
    var Widget = require('bitbucket/internal/bbui/widget/widget');

    var testCases = [
        {
            existing: {
                mirrors: [],
                requests: [],
            },
            expectedPos: 0,
            insert: {type: 'mirror', id: 42, name: 'C'},
        },
        {
            existing: {
                mirrors: [{id: 40, name: 'A'}, {id: 42, name: 'C'}],
                requests: [],
            },
            expectedPos: 0,
            insert: {type: 'mirror', id: 99, name: 'B'},
        },
        {
            existing: {
                mirrors: [],
                requests: [{id: 40, mirrorName: 'A'}, {id: 42, mirrorName: 'C'}],
            },
            expectedPos: 0,
            insert: {type: 'request', id: 99, mirrorName: 'B'},
        },
        {
            existing: {
                mirrors: [{id: 1, name: 'A'}, {id: 2, name: 'C'}],
                requests: [{id: 40, mirrorName: 'A'}, {id: 42, mirrorName: 'C'}],
            },
            expectedPos: 0,
            insert: {type: 'request', id: 99, mirrorName: 'B'},
        },
        {
            existing: {
                mirrors: [{id: 1, name: 'A'}, {id: 2, name: 'C'}],
                requests: [{id: 40, mirrorName: 'A'}, {id: 42, mirrorName: 'C'}],
            },
            expectedPos: 0,
            insert: {type: 'mirror', id: 99, name: 'B'},
        },
        {
            existing: {
                mirrors: [{id: 1, name: 'A'}, {id: 2, name: 'C'}],
                requests: [{id: 40, mirrorName: 'A'}, {id: 42, mirrorName: 'C'}],
            },
            expectedPos: 0,
            insert: {type: 'mirror', id: 99, name: 'D'},
        },
        {
            existing: {
                mirrors: [{id: 1, name: 'A'}, {id: 2, name: 'C'}],
                requests: [{id: 40, mirrorName: 'B'}, {id: 42, mirrorName: 'C'}],
            },
            expectedPos: 0,
            insert: {type: 'request', id: 99, mirrorName: 'A'},
        },
    ];

    function SimpleWidget() {
        Widget.call(this);
    }
    SimpleWidget.prototype = Object.create(Widget.prototype);

    var views = {
        request: SimpleWidget,
        mirror: SimpleWidget,
    };

    QUnit.module('mirroring-admin', {
        beforeEach: function () {
            this.$fixture = $('#qunit-fixture');
            this.server = sinon.fakeServer.create();
        },
        afterEach: function () {
            this.view.destroy();
            delete this.$fixture;
            this.server.restore();
        },
    });

    testCases.forEach(function (testCase, i) {
        QUnit.test('findBeforeElement test case ' + i, function (assert) {
            assert.expect(2);
            this.view = new MirroringAdminView(this.$fixture, {
                mirrors: testCase.existing.mirrors,
                requests: testCase.existing.requests,
                views: views,
            });

            var $item = this.view.findBeforeElement(testCase.insert.type, testCase.insert);

            assert.ok($item, 'found a before element');

            var index = this.view.listAndDetailView.$listView.find('li, a').index($item);

            assert.equal(index, testCase.expectedPos);
        });
    });

    QUnit.test('Unavailable option shows extra copy', function (assert) {
        this.view = new MirroringAdminView(this.$fixture, {
            mirrors: [],
            requests: [],
            unavailable: false,
            views: views,
        });

        assert.ok(this.view.$el.find('.unavailable-message').length === 0, 'No message shown when feature is available');

        this.view = new MirroringAdminView(this.$fixture, {
            mirrors: [],
            requests: [],
            unavailable: true,
            unavailableMessage: 'Can\'t touch this',
            views: views,
        });

        assert.ok(this.view.$el.find('.unavailable-message').length === 1, 'Message shown when feature is unavailable');
    });

    QUnit.test('Approving mirror in one tab removes the request from another on poll', function (assert) {
        var done = assert.async();

        this.server.respondWith('GET', /rest\/mirroring\/latest\/requests.*/, [200, {'Content-Type': 'application/json'}, JSON.stringify({
            values: [],
        })]);

        this.server.respondWith('GET', /rest\/mirroring\/latest\/mirrorServers.*/, [200, {'Content-Type': 'application/json'}, JSON.stringify({
            values: [{
                id: 88,
                name: 'A',
            }],
        })]);

        this.view = new MirroringAdminView(this.$fixture, {
            mirrors: [],
            requests: [{id: 40, mirrorName: 'A', baseUrl: ''}],
            unavailable: false,
            views: views,
        });

        assert.strictEqual(1, Object.keys(this.view.navListItems.request).length, 'There is one request.');
        assert.strictEqual(0, Object.keys(this.view.navListItems.mirror).length, 'There are no mirrors.');

        var self = this;

        // the request in the mirroring UI happens on the next tick even with polling disabled (timeout === 0)
        setTimeout(function () {
            self.server.respond();
        }, 0);

        this.view.refreshList().done(function () {
            assert.strictEqual(0, Object.keys(self.view.navListItems.request).length, 'There are no requests.');
            assert.strictEqual(1, Object.keys(self.view.navListItems.mirror).length, 'There is one mirror.');
            done();
        }).fail(function (err) {
            done(err);
        });
    });

    QUnit.test('Mirror marked online when /status is 200 OK', function (assert) {
        var done = assert.async();
        this.server.respondWith('HEAD', /.*\/status/, [200, {'Content-Type': 'application/json'}, JSON.stringify({
            state: 'RUNNING',
        })]);

        var mirror = {id: 1, name: 'A', baseUrl: 'https://mirror.com'};
        this.view = new MirroringAdminView(this.$fixture, {
            mirrors: [mirror],
            requests: [],
            unavailable: false,
            views: views,
        });

        this.server.respond();

        var self = this;
        this.view._healthCheck.done(function (status1) {
            assert.strictEqual(status1, 'online', 'Health check promise resolved correctly');
            var $mirror = self.view.listAndDetailView.$listView.find('.mirror');
            assert.ok($mirror.find('.status').hasClass('online'), 'Mirror showing correct status');
            done();
        });
    });
});