/* global AJS:false */
AJS.test.require("com.atlassian.bitbucket.server.bitbucket-web-api:branch-selector-field", function() {
    var $ = jQuery;
    var ajax = require('bitbucket/internal/util/ajax');
    var Project = require('bitbucket/internal/model/project');
    var Repository = require('bitbucket/internal/model/repository');

    var events = require('bitbucket/util/events');

    var STEP = 100;

    var pageState = require('bitbucket/internal/model/page-state');
    pageState.setProject(new Project({ key : 'PROJ' }));
    pageState.setRepository(new Repository({slug: 'SLUG', project: { key: 'PROJ' } }));


    var mockRefJson = {
        displayId: "master",
        id: "refs/heads/master",
        isDefault: true,
        latestCommit: "9fa7c613b137c96af6c9f100ff1234d28e9182d8"
    };

    var mockTagJson = {
        displayId: "1.0",
        id: "refs/tags/1.0",
        isDefault: true,
        latestCommit: "9fa7c613b137c96af6c9f100ff1234d28e9182d8"
    };

    sinon.stub(ajax, 'rest', function() {
        var promise = $.Deferred().resolve({
            values : [ mockRefJson ],
            start : 0,
            limit : 25,
            size : 1,
            isLastPage : true,
            nextPageStart : null
        });
        promise.abort = $.noop;
        return promise;
    });

    module('branch-selector-field', {
        setup : function() {
        },
        teardown : function() {
            $('.aui-inline-dialog').remove();
        }
    });

    function testTemplate(name, inputs) {
        test(name, function() {
            var $generated = $(bitbucket.component.branchSelector.field(inputs));

            var $label = $generated.find('label');
            var $input = $generated.find('input');
            var $trigger = $generated.find('.branch-selector-field');
            var $required = $generated.find('.icon-required');
            var $remove = $generated.find('.remove-link');
            var $description = $generated.find('.description');
            var $errors = $generated.find('.error');

            equal($label.text().substring(0, inputs.labelText.length), inputs.labelText, 'Label text is correct');
            equal($input.attr('id'), inputs.id || inputs.name, 'Input id is correct');
            equal($input.attr('name'), inputs.name || inputs.id, 'Input name is correct');
            equal(!!$required.length, !!inputs.isRequired, 'Required icon is displayed only when required.');
            equal($trigger.text(), 'Select revision', 'Initial displayed value is correct');
            equal($remove.hasClass('hidden'), !inputs.initialValue, 'remove button should only show if there is a value.');
            equal($description.text(), inputs.descriptionText || '', 'Description text is correct.');
            equal($errors.length, inputs.errorTexts ? inputs.errorTexts.length : 0, 'Correct number of errors.');
            $errors.each(function(i) {
                equal($(this).text(), inputs.errorTexts[i], 'Error ' + i + ' has correct text.');
            });
        });
    }
    testTemplate('template accepts all inputs', {
        id : 'ID',
        name : 'NAME',
        labelText : 'LABEL',
        isRequired : true,
        descriptionText : 'DESCRIPTION',
        errorTexts : ['ERROR', 'ERROR2'],
        initialValue : 'VALUE',
        enableBranchLinks : true,
        showTags: true
    });
    testTemplate('template accepts minimum inputs', {
        id : 'ID',
        labelText : 'LABEL'
    });
    testTemplate('template accepts alternate minimum inputs', {
        name : 'NAME',
        labelText : 'LABEL'
    });


    asyncTest("Dialog opens on click", function() {
        equal($('.aui-inline-dialog:visible').length, 0, "No InlineDialogs visible to start with");

        $(bitbucket.component.branchSelector.field({
            id : 'ID',
            labelText : 'LABEL'
        })).appendTo('#qunit-fixture').find('.branch-selector-field').click();

        setTimeout(function() {
            equal($('.aui-inline-dialog:visible').length, 1, "One InlineDialog visible");

            start();
        }, STEP);
    });

    asyncTest("Display ID is set when initial ID of tag is provided", function() {
        var $field = $(bitbucket.component.branchSelector.field({
            id : 'ID',
            labelText : 'LABEL',
            initialValue : mockTagJson.id
        })).appendTo('#qunit-fixture');
        setTimeout(function() {
            equal($field.find('.branch-selector-field .name').text(), mockTagJson.displayId,
                "Display ID is set correctly when HTML is added to DOM.");

            start();
        }, STEP);
    });

    asyncTest("Display ID is set when initial ID of branch is provided", function() {
        var $field = $(bitbucket.component.branchSelector.field({
            id : 'ID',
            labelText : 'LABEL',
            initialValue : mockRefJson.id
        })).appendTo('#qunit-fixture');
        setTimeout(function() {
            equal($field.find('.branch-selector-field .name').text(), mockRefJson.displayId,
                "Display ID is set correctly when HTML is added to DOM.");

            start();
        }, STEP);
    });

    asyncTest("showTags is honored when true (there is a branches tab and a tags tab)", function() {
        equal($('.aui-inline-dialog:visible').length, 0, "No InlineDialogs visible to start with");

        $(bitbucket.component.branchSelector.field({
            id : 'ID',
            labelText : 'LABEL',
            showTags: true
        })).appendTo('#qunit-fixture').find('.branch-selector-field').click();

        setTimeout(function() {
            equal($('.aui-inline-dialog:visible').length, 1, "One InlineDialog visible");
            equal($('.aui-inline-dialog .tabs-menu > .menu-item:visible').length, 2, "There are two tabs in the branch selector");
            start();
        }, STEP);

    });

    asyncTest("showTags is honored when false (no tabs and only branches shown)", function() {
        equal($('.aui-inline-dialog:visible').length, 0, "No InlineDialogs visible to start with");

        $(bitbucket.component.branchSelector.field({
            id : 'ID',
            labelText : 'LABEL',
            showTags: false
        })).appendTo('#qunit-fixture').find('.branch-selector-field').click();

        setTimeout(function() {
            equal($('.aui-inline-dialog:visible').length, 1, "One InlineDialog visible");
            equal($('.aui-inline-dialog .tabs-menu > .menu-item:visible').length, 0, "There are no tabs in the branch selector");
            start();
        }, STEP);
    });
    asyncTest("Selecting sets input and shows remove button, remove button unsets.", function() {

        var $field = $(bitbucket.component.branchSelector.field({
            id : 'ID',
            labelText : 'LABEL'
        })).appendTo('#qunit-fixture');

        var $input = $field.find('input');
        var $remove = $field.find('.remove-link');

        $field.find('.branch-selector-field').click();
        setTimeout(function() {
            var $firstResult = $('.aui-inline-dialog').find('.result a').eq(0);
            ok($firstResult.length, 'result was found.');

            $firstResult.click();

            setTimeout(function() {
                equal($input.val(), mockRefJson.id, 'Input was set on clicking');
                equal($remove.hasClass('hidden'), false, 'Remove link should be shown');

                $remove.click();
                setTimeout(function() {
                    equal($input.val(), '', 'Input was unset on clicking remove');
                    equal($remove.hasClass('hidden'), true, 'Remove link should be hidden');

                    start();
                }, STEP);
            }, STEP);
        }, STEP);
    });

    asyncTest("repeated calls don't create multiple InlineDialogs", function() {
        equal($('.aui-inline-dialog').length, 0, "No InlineDialogs to start with");

        $(bitbucket.component.branchSelector.field({
            id : 'ID',
            labelText : 'LABEL'
        })).appendTo('#qunit-fixture').find('.branch-selector-field').click();
        setTimeout(function() {
            equal($('.aui-inline-dialog').length, 1, "One InlineDialog created");

            $(bitbucket.component.branchSelector.field({
                id : 'ID',
                labelText : 'LABEL'
            })).appendTo('#qunit-fixture').find('.branch-selector-field').click();
            setTimeout(function() {
                equal($('.aui-inline-dialog').length, 1, "Still one InlineDialog created");

                start();
            }, STEP);
        }, STEP);
    });

    asyncTest("BranchSelectorField interactions aren't conflated", function() {

        var $field1 = $(bitbucket.component.branchSelector.field({
            id : 'ID1',
            labelText : 'LABEL'
        })).appendTo('#qunit-fixture');
        var $input1 = $field1.find('input');
        var $remove1 = $field1.find('.remove-link');

        $field1.find('.branch-selector-field').click();

        setTimeout(function() {

            var $field2 = $(bitbucket.component.branchSelector.field({
                id : 'ID2',
                labelText : 'LABEL'
            })).appendTo('#qunit-fixture');
            var $input2 = $field2.find('input');
            var $remove2 = $field2.find('.remove-link');

            $field2.find('.branch-selector-field').click();

            setTimeout(function() {
                var $firstResult = $('.aui-inline-dialog').find('.result a').eq(1);
                ok($firstResult.length, 'result was found.');
                $firstResult.click();

                setTimeout(function() {
                    equal($input1.val(), '', 'Input on 1 was unaffected');
                    equal($remove1.hasClass('hidden'), true, 'Remove link on 1 should be hidden');

                    equal($input2.val(), mockRefJson.id, 'Input on 2 was set on clicking');
                    equal($remove2.hasClass('hidden'), false, 'Remove link on 2 should be shown');

                    start();
                }, STEP);
            }, STEP);
        }, STEP);
    });

    asyncTest("preloadData is supported", function() {

        $(bitbucket.component.branchSelector.field({
            id : 'ID',
            labelText : 'LABEL',
            showTags: false,
            preloadData: [{
                id: 'test-id',
                displayId: 'Test option',
                type: 'branch'
            }]
        })).appendTo('#qunit-fixture').find('.branch-selector-field').click();

        var preloadOption = $('.aui-inline-dialog .results li.result a[data-id="test-id"]');
        equal(preloadOption.length, 1, "Default Branch option should be in the results list");

        setTimeout(start);
    });

    asyncTest("selects item from preloadData properly", function() {
        var $field = $(bitbucket.component.branchSelector.field({
            id : 'ID',
            labelText : 'LABEL',
            showTags: false,
            initialValue : 'test-id',
            preloadData: [{
                id: 'test-id',
                displayId: 'Test option',
                type: 'branch'
            }]
        })).appendTo('#qunit-fixture');

        setTimeout(function() {
            equal($field.find('.branch-selector-field .name').text(), 'Test option',
                "Display ID of preloadData item is set correctly when HTML is added to DOM.");
            start();
        }, STEP);
    });

    asyncTest("field appended to jQuery object first then to DOM", function() {
        var $container = $('<div id="container"></div>');
        var $field = $(bitbucket.component.branchSelector.field({
            id : 'ID',
            labelText : 'LABEL'
        }));
        $container.append($field).appendTo('#qunit-fixture');

        setTimeout(function() {
            $field.find('.branch-selector-field').click();

            setTimeout(function() {
                equal($('.aui-inline-dialog:visible').length, 1, "One InlineDialog visible");

                start();
            }, STEP);
        }, 0);
    });

    asyncTest("it fires an event", function () {
        var $field = $(bitbucket.component.branchSelector.field({
            id : 'ID',
            labelText : 'LABEL'
        })).appendTo('#qunit-fixture').find('.branch-selector-field').click();

        var eventHandler = sinon.spy();
        events.on('bitbucket.component.branchSelector.change', eventHandler);

        setTimeout(function() {
            var $firstResult = $('.aui-inline-dialog').find('.result a').first();
            ok($firstResult.length, 'result was found.');
            $firstResult.click();

            ok(eventHandler.calledOnce);
            var data = eventHandler.firstCall.args[0];
            equal(typeof data, "object", "Data is an object");
            equal(data.elementId, "ID");
            equal(data.ref.id, "refs/heads/master");
            start();
        }, 0);
    });

});