(function()
{
    var TasksPermissionChecker = require('./tasks.permission_checker.class.js');

    var template = require('../../html/project/tasks_list.directive.html');
	var moduleName = 'claromentis.project';

	angular.module(moduleName)
        .directive('clangProjectTasksList', projectTasksList);

	projectTasksList.$inject = ['Task', 'tasksService'];
    function projectTasksList(Task, service) {
        return {
            restrict: 'E',
            templateUrl: template,
            scope: {
                tasks: '<',
                perms: '<',
                isMobile: '<'
            },
            controllerAs: 'ctrl',
            bindToController: true,
            controller: controller
        };

        function controller()
        {
            var ctrl = this;

            ctrl.$onInit = function() {
                ctrl.permsChecker = new TasksPermissionChecker(ctrl.perms);
            }

            ctrl.tasksService = service;

            ctrl.HasTaskDragPerms = function(task, listId) {
                if (ctrl.isMobile)
                    return false;

                return ctrl.permsChecker.HasTaskDragPerms(task, listId);
            };

            ctrl.HasListDragPerms = function() {
                if (ctrl.isMobile)
                    return false;

                return ctrl.permsChecker.HasListDragPerms();
            };

            ctrl.IsMyTask = function(task) {
                return ctrl.permsChecker.IsMyTask(task);
            }

            ctrl.CanEditMyOwnTask = function(task) {
                return ctrl.permsChecker.CanEditMyOwnTask(task);
            }

            ctrl.CanUpdateMyTaskStatus = function(task, listId) {
                return ctrl.permsChecker.CanUpdateMyTaskStatus(task, listId);
            }

            /**
             * Called while dragging to determine where items can be dropped. Because we have both task and section containers we find
             * the types involved and limit items to only be dropped in a container of their own kind. If this is not done we can drop
             * tasks as a section and vice versa.
             */
            ctrl.dragAccept = function (sourceItemHandleScope, destSortableScope)
            {
                var sourceType = '';
                if ('task' in sourceItemHandleScope.itemScope.$parent)
                    sourceType = 'Task';
                else if ('list_entry' in sourceItemHandleScope.itemScope.$parent)
                    sourceType = 'Section';

                var destType = destSortableScope.options.dropType;

                if (sourceType === destType)
                {
                    if ((sourceType === 'Section') &&
                        (!ctrl.perms.can_edit_any_task))
                    {
                        return false;
                    }

                    if (sourceType === 'Task')
                    {
                        if (ctrl.perms.can_edit_any_task)
                            return true;

                        var task = sourceItemHandleScope.itemScope.$parent.task;

                        if (ctrl.CanEditMyOwnTask(task))
                            return true;

                        if (ctrl.CanUpdateMyTaskStatus(task, destSortableScope.element.data('list-id')))
                            return true;

                        // Can only drag in the circumstances above
                        return false;
                    }

                    // Other combos are fine
                    return true;
                }

                // Can't drag between types at all
                return false;
            };

            ctrl.taskOrderChanged = function(data)
            {
                var destList = data.dest.sortableScope.$parent.$parent.ctrl.list;

                var taskId = parseInt(destList.tasks[data.dest.index].id);

                var newOrder = [];
                for (var taskIndex = 0; taskIndex < destList.tasks.length; taskIndex++)
                {
                    newOrder.push(parseInt(destList.tasks[taskIndex].id));
                }

                var newData = {
                    listId: parseInt(destList.list.id),
                    order: newOrder
                };

                service.updateTaskOrder(taskId, newData);
            };

            ctrl.sectionOrderChanged = function(data)
            {
                service.updateListOrder(data.source.itemScope.$parent.list_entry.list.id, data.dest.index);
            };

            ctrl.dragTaskListeners =
            {
                dropType: 'Task',
                accept: ctrl.dragAccept,
                itemMoved: ctrl.taskOrderChanged,
                orderChanged: ctrl.taskOrderChanged,
                containment: '.js-drag-container',
                containerPositioning: 'relative'
            };

            ctrl.dragSectionListeners =
            {
                dropType: 'Section',
                accept: ctrl.dragAccept,
                orderChanged: ctrl.sectionOrderChanged,
                containment: '.js-drag-container',
                containerPositioning: 'relative'
            };

            ctrl.taskDeletedCallback = function(task)
            {
                service.deleteTask(task.id)
            };

            ctrl.taskCompleteToggledCallback = function(task)
            {
                service.toggleCompleted(task.id);
            };
        }
    }
}());
