define([
    'lodash',
    'bitbucket/internal/feature/tasks/model/task',
    'bitbucket/internal/feature/tasks/model/task-collection',
    'bitbucket/internal/feature/tasks/model/task-state',
    'bitbucket/internal/feature/tasks/task-list/task-list-table',
    'bitbucket/internal/util/function'
], function (
    _,
    Task,
    TaskCollection,
    TaskState,
    TaskListTable,
    fn
) {

    'use strict';

    module('tasks-task-list-table', {
        setup: function () {
            this.collection = new TaskCollection();
            this.$el = $("<ul class='task-list'></ul>");
            $('body').append(this.$el);
            this.context = {
                projectKey: 'AAA',
                repository: {},
                pullRequestId: 1
            };

            fn.set('bitbucket.internal.feature.tasks.taskList.dialogEmptyMessage', sinon.spy(), true)(window);

            this.table = new TaskListTable(this.$el, this.$el, this.collection, this.context);

            this.setupTasksFromObjectArray = function (taskObjects) {
                var tasks = [];
                var self = this;
                taskObjects.forEach(function (taskJSON) {
                    var task = new Task(taskJSON);
                    tasks.push(task);
                    self.collection.add(task);
                    var stubView = {
                        model: task,
                        remove: sinon.spy()
                    };
                    task.stubView = stubView; // hack for testing
                    self.table._taskRowViews.push(stubView);
                });

                var isResolved = _.compose(fn.eq(TaskState.RESOLVED), fn.invoke('getState'));
                if(tasks.some(isResolved)) {
                    var $subHeading = $("<li class='section-heading'>Heading</li>");
                    this.$el.append($subHeading);
                }
                return tasks;
            };
        },
        teardown: function () {
            this.$el.remove();
        }
    });

    test('TaskListTable handles a task being destroyed', function () {
        var tasks = this.setupTasksFromObjectArray([{
            id: 1,
            state: TaskState.OPEN
        }]);

        sinon.spy(this.table, '_addNoRowsMessage');

        this.table._onTaskDestroy(tasks[0]);

        equal(this.table._taskRowViews.length, 0);
        ok(tasks[0].stubView.remove.calledOnce, 'stub view was removed');
        ok(this.table._addNoRowsMessage.calledOnce, 'No row message added');
        this.table._addNoRowsMessage.restore();
    });

    test('TaskListTable removed resolved tasks heading when all resolved tasks are removed', function () {
        this.setupTasksFromObjectArray([{
            id: 1,
            state: TaskState.OPEN
        },
        {
            id: 2,
            state: TaskState.RESOLVED
        }]);

        sinon.spy(this.table, '_addNoRowsMessage');
        var row = this.table._taskRowViews[1];
        var task = row.model;

        task.set({
            state: TaskState.DELETED,
            lastState: TaskState.RESOLVED
        });

        this.table._onTaskDestroy(task);

        equal(this.table._taskRowViews.length, 1);
        ok(this.table._taskRowViews[0].remove.notCalled, "first stub view wasn't removed");
        ok(row.remove.calledOnce, "second stub view was removed");
        ok(this.table._addNoRowsMessage.notCalled, "No row message wasn't added");
        equal(this.$el.find('.section-heading').length, 0);
        this.table._addNoRowsMessage.restore();
    });

    test("TaskListTable doesn't remove resolved tasks heading when resolved tasks remain", function () {

        this.setupTasksFromObjectArray([{
            id: 1,
            state: TaskState.OPEN
        },
        {
            id: 2,
            state: TaskState.RESOLVED
        },
        {
            id: 3,
            state: TaskState.RESOLVED
        }
        ]);

        sinon.spy(this.table, '_addNoRowsMessage');
        var row = this.table._taskRowViews[1];
        var task = row.model;
        task.set({
            state: TaskState.DELETED,
            lastState: TaskState.RESOLVED
        });
        this.table._onTaskDestroy(task);

        equal(this.table._taskRowViews.length, 2);
        ok(this.table._taskRowViews[0].remove.notCalled, "first stub view wasn't removed");
        ok(row.remove.calledOnce, "second stub view was removed");
        ok(this.table._taskRowViews[1].remove.notCalled, "third stub view was removed");
        ok(this.table._addNoRowsMessage.notCalled, "No row message was't added");
        equal(this.$el.find('.section-heading').length, 1, "Resovled tasks heading remains");
        this.table._addNoRowsMessage.restore();
    });
});
