define([
    'jquery',
    'lodash',
    'Squire',
    'test-helper',
    'bitbucket/internal/test/waiter'
], function (
    $,
    _,
    Squire,
    testHelper,
    createWaiter
) {

    'use strict';

    var fixtureHtml = '<div class="commit-files">' +
        '<div class="file-tree-container">' +
        '   <div class="diff-tree-toolbar">' +
        '       <input type="text" />' +
        '       <div class="collapse-file-tree"></div>' +
        '   </div>' +
        '   <div class="file-tree-wrapper"></div>' +
        '</div>' +
        '</div>';

    var injector = new Squire();
    injector.setDefaultDeps(['bitbucket/internal/feature/commit/tree-and-diff-view']);
    injector.mock('jquery', $);

    module('tree-and-diff-view', {
        beforeEach: function () {
            this.beforeHash = window.location.hash;
            this.$fixture = $('#qunit-fixture');
            this.$fixture.html(fixtureHtml);

            this.$collapseButton = this.$fixture.find('.collapse-file-tree');
            this.$input = this.$fixture.find('input');
            this.$fileBrowser = this.$fixture.find('.file-tree-container');
            this.$fileBrowserWrapper = this.$fixture.find('.file-tree-wrapper');
            this.$container = this.$fixture.find('.commit-files');

            window.WRM = testHelper.mockWRM({
                'com.atlassian.bitbucket.server.config-wrm-data:attachment.upload.max.size.data': {
                    value: 10485760,
                    type: 'NUMBER'
                }
            });
        },
        afterEach: function () {
            this.$fixture.empty();
            this.$fixture = null;
            window.location.hash = this.beforeHash;
        }
    });

    injector.test('Collapse button should toggle the file browser', function (assert, treeAndDiffView) {
        treeAndDiffView._initDiffTreeToggle();

        assert.equal(this.$container.is('.collapsed'), false, 'Container should be expanded by default.');

        this.$collapseButton.trigger('click');
        assert.equal(this.$container.is('.collapsed'), true, 'Container should collapse after toggling.');

        this.$collapseButton.trigger('click');
        assert.equal(this.$container.is('.collapsed'), false, 'Container should become expanded after second toggling.');
    });

    injector.test('Collapsed file browser should expand when you focus on the search box', function(assert, treeAndDiffView) {
        treeAndDiffView._initDiffTreeToggle();
        var self = this;

        self.$collapseButton.trigger('click');
        assert.equal(self.$container.is('.collapsed'), true, 'Container should collapse after toggling.');

        self.$input.trigger('focus');
        assert.equal(self.$container.is('.collapsed'), false, 'Container should expand after place focus on the search box.');
    });

    injector.test('Collapsed file browser should be able to quick-revealed', function(assert, treeAndDiffView) {
        treeAndDiffView._initDiffTreeToggle();
        var self = this;
        var waiter = createWaiter(assert);

        // collapse the file browser first
        self.$collapseButton.trigger('click');

        self.$fileBrowserWrapper.trigger('mouseenter');
        waiter.waitFor({
            predicate: function () {
                return self.$container.is('.quick-reveal-mode:not(.collapsed)');
            },
            message: 'File browser should expanded because of quick revealing.'
        }).then(function() {
            self.$fileBrowserWrapper.trigger('mouseleave');
        }).then(waiter.thenWaitFor({
            predicate: function () {
                return self.$container.is('.collapsed:not(.quick-reveal-mode)');
            },
            message: 'File browser should collapse because we leave the file browser.'
        })).always(waiter.resume);
    });

    injector.test('Collapsed file browser should expand and quit quick reveal mode when it is forced to expand', function(assert, treeAndDiffView) {
        treeAndDiffView._initDiffTreeToggle();
        var self = this;
        var waiter = createWaiter(assert);

        // collapse the file browser first
        self.$collapseButton.trigger('click');

        // enter quick reveal mode
        self.$fileBrowserWrapper.trigger('mouseenter');
        waiter.waitFor({
            predicate: $.fn.is.bind(self.$container, '.quick-reveal-mode:not(.collapsed)'),
            message: 'File browser should expanded at quick reveal mode'
        }).then(function() {
            self.$collapseButton.trigger('click');
        }).then(waiter.thenWaitFor({
            predicate: $.fn.is.bind(self.$container, ':not(.collapsed):not(.quick-reveal-mode)'),
            message: 'File browser should stay expanded because you click on the toggle button'
        })).then(function() {
            self.$fileBrowserWrapper.trigger('mouseleave');
        }).then(waiter.thenWaitFor({
            predicate: $.fn.is.bind(self.$container, ':not(.collapsed):not(.quick-reveal-mode)'),
            message: 'File browser should remain expanded even your mouse leaves the file browser.'
        })).always(waiter.resume);
    });

    injector.test('Collapsed file browser should expand and quit quick reveal mode when you focus on the input', function(assert, treeAndDiffView) {
        treeAndDiffView._initDiffTreeToggle();
        var self = this;
        var waiter = createWaiter(assert);

        // collapse the file browser first
        self.$collapseButton.trigger('click');

        // enter quick reveal mode
        self.$fileBrowserWrapper.trigger('mouseenter');
        waiter.waitFor({
            predicate: $.fn.is.bind(self.$container, ':not(.collapsed).quick-reveal-mode'),
            message: 'File browser should expanded at quick reveal mode'
        }).then(function() {
            self.$input.focus();
        }).then(waiter.thenWaitFor({
            predicate: $.fn.is.bind(self.$container, ':not(.collapsed):not(.quick-reveal-mode)'),
            message: 'File browser should stay expanded because the search box is focused'
        })).then(function() {
            self.$fileBrowserWrapper.trigger('mouseleave');
        }).then(waiter.thenWaitFor({
            predicate: $.fn.is.bind(self.$container, ':not(.collapsed):not(.quick-reveal-mode)'),
            message: 'File browser should remain expanded even your mouse leaves the file browser.'
        })).always(waiter.resume);
    });

    injector.test('Percentage sign in file should still allow file navigation', function(assert, treeAndDiffView) {
        treeAndDiffView._onSelectedNodeChanged({data: _.constant("A%B")});
        assert.equal(window.location.hash, "#A%25B");

        treeAndDiffView._onSelectedNodeChanged({data: _.constant("A[B")});
        assert.equal(window.location.hash, "#A%5BB");

        treeAndDiffView._onSelectedNodeChanged({data: _.constant("ab/A[B")});
        assert.equal(window.location.hash, "#ab/A%5BB");
    });
});