/* Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Assignment
 */
'use strict';

angular.module('flowableModeler').controller('FlowableAssignmentCtrl', [ '$scope', '$modal', function($scope, $modal) {

    // Config for the modal window
    var opts = {
        template:  'editor-app/configuration/properties/assignment-popup.html?version=' + Date.now(),
        scope: $scope
    };

    // Open the dialog
    _internalCreateModal(opts, $modal, $scope);
}]);

angular.module('flowableModeler').controller('FlowableAssignmentPopupCtrl',
    [ '$rootScope', '$scope', '$translate', '$http', 'UserService', 'GroupService', function($rootScope, $scope, $translate, $http, UserService, GroupService) {

    // Put json representing assignment on scope
    if ($scope.property.value !== undefined && $scope.property.value !== null
        && $scope.property.value.assignment !== undefined
        && $scope.property.value.assignment !== null) {

        $scope.assignment = $scope.property.value.assignment;
        if (typeof $scope.assignment.type === 'undefined') {
            $scope.assignment.type = 'static';
        }

    } else {
        $scope.assignment = {type:'idm'};
    }

    $scope.popup = {
        assignmentObject: {
            type:$scope.assignment.type,
            idm: {
                type:undefined,
                assignee: undefined,
                candidateUsers: [],
                candidateGroups: []
            },
            static: {
                assignee: undefined,
                candidateUsers: [],
                candidateGroups: []
            }
        }
    };


    $scope.assignmentOptions = [
        {id: "initiator", title: $translate.instant('PROPERTY.ASSIGNMENT.IDM.DROPDOWN.INITIATOR')},
        {id: "user", title: $translate.instant('PROPERTY.ASSIGNMENT.IDM.DROPDOWN.USER')},
        {id: "users", title: $translate.instant('PROPERTY.ASSIGNMENT.IDM.DROPDOWN.USERS')},
        {id: "groups", title: $translate.instant('PROPERTY.ASSIGNMENT.IDM.DROPDOWN.GROUPS')}
    ];

    if ($scope.assignment.idm && $scope.assignment.idm.type) {
        for (var i = 0; i < $scope.assignmentOptions.length; i++) {
            if ($scope.assignmentOptions[i].id == $scope.assignment.idm.type) {
                $scope.assignmentOption = $scope.assignmentOptions[i];
                break;
            }
        }
    }

    // fill the IDM area
    if (!$scope.assignmentOption) {
        // Default, first time opening the popup
        $scope.assignmentOption = $scope.assignmentOptions[0];
    } else {
        // Values already filled
        if ($scope.assignment.idm) { //fill the IDM tab
            if ($scope.assignment.idm.assignee) {
                if ($scope.assignment.idm.assignee.id) {
                    $scope.popup.assignmentObject.idm.assignee = $scope.assignment.idm.assignee;
                } else {
                    $scope.popup.assignmentObject.idm.assignee = {email: $scope.assignment.idm.assignee.email};
                }
            }

            if ($scope.assignment.idm.candidateUsers && $scope.assignment.idm.candidateUsers.length > 0) {
                for (var i = 0; i < $scope.assignment.idm.candidateUsers.length; i++) {
                    $scope.popup.assignmentObject.idm.candidateUsers.push($scope.assignment.idm.candidateUsers[i]);
                }
            }

            if ($scope.assignment.idm.candidateGroups && $scope.assignment.idm.candidateGroups.length > 0) {
                for (var i = 0; i < $scope.assignment.idm.candidateGroups.length; i++) {
                    $scope.popup.assignmentObject.idm.candidateGroups.push($scope.assignment.idm.candidateGroups[i]);
                }
            }
        }
    }
    
    //fill the static area
    if ($scope.assignment.assignee) {
        $scope.popup.assignmentObject.static.assignee = $scope.assignment.assignee;
    }

    if ($scope.assignment.candidateUsers && $scope.assignment.candidateUsers.length > 0) {
        for (var i = 0; i < $scope.assignment.candidateUsers.length; i++) {
            $scope.popup.assignmentObject.static.candidateUsers.push($scope.assignment.candidateUsers[i]);
        }
    }

    if ($scope.assignment.candidateGroups && $scope.assignment.candidateGroups.length > 0) {
        for (var i = 0; i < $scope.assignment.candidateGroups.length; i++) {
            $scope.popup.assignmentObject.static.candidateGroups.push($scope.assignment.candidateGroups[i]);
        }
    }

    initStaticContextForEditing($scope);

    $scope.$watch('popup.groupFilter', function () {
        $scope.updateGroupFilter();
    });

    $scope.$watch('popup.filter', function() {
        $scope.updateFilter();
    });

    $scope.updateFilter = function() {
        if ($scope.popup.oldFilter == undefined || $scope.popup.oldFilter != $scope.popup.filter) {
            if (!$scope.popup.filter) {
                $scope.popup.oldFilter = '';
            } else {
                $scope.popup.oldFilter = $scope.popup.filter;
            }

            if ($scope.popup.filter !== null && $scope.popup.filter !== undefined) {
                UserService.getFilteredUsers($scope.popup.filter).then(function (result) {
                    var filteredUsers = [];
                    for (var i=0; i<result.data.length; i++) {
                        var filteredUser = result.data[i];

                        var foundCandidateUser = false;
                        if ($scope.popup.assignmentObject.idm.candidateUsers !== null && $scope.popup.assignmentObject.idm.candidateUsers !== undefined) {
                            for (var j=0; j<$scope.popup.assignmentObject.idm.candidateUsers.length; j++) {
                                var candidateUser = $scope.popup.assignmentObject.idm.candidateUsers[j];
                                if (candidateUser.id === filteredUser.id) {
                                    foundCandidateUser = true;
                                    break;
                                }
                            }
                        }

                        if (!foundCandidateUser) {
                            filteredUsers.push(filteredUser);
                        }

                    }

                    $scope.popup.userResults = filteredUsers;
                    $scope.resetSelection();
                });
            }
        }
    };

    $scope.updateGroupFilter = function() {
        if ($scope.popup.oldGroupFilter == undefined || $scope.popup.oldGroupFilter != $scope.popup.groupFilter) {
            if (!$scope.popup.groupFilter) {
                $scope.popup.oldGroupFilter = '';
            } else {
                $scope.popup.oldGroupFilter = $scope.popup.groupFilter;
            }

            GroupService.getFilteredGroups($scope.popup.groupFilter).then(function(result) {
                $scope.popup.groupResults = result.data;
                $scope.resetGroupSelection();
            });
        }
    };

    $scope.confirmUser = function(user) {
        if (!user) {
            // Selection is done with keyboard, use selection index
            var users = $scope.popup.userResults;
            if ($scope.popup.selectedIndex >= 0 && $scope.popup.selectedIndex < users.length) {
                user = users[$scope.popup.selectedIndex];
            }
        }

        if (user) {
            if ("user" == $scope.assignmentOption.id) {
                $scope.popup.assignmentObject.idm.assignee = user;
            } else if ("users" == $scope.assignmentOption.id) {

                // Only add if not yet part of candidate users
                var found = false;
                if ($scope.popup.assignmentObject.idm.candidateUsers) {
                    for (var i = 0; i < $scope.popup.assignmentObject.idm.candidateUsers.length; i++) {
                        if ($scope.popup.assignmentObject.idm.candidateUsers[i].id === user.id) {
                            found = true;
                            break;
                        }
                    }
                }

                if (!found) {
                    $scope.addCandidateUser(user);
                }
            }
        }
    };

    $scope.confirmEmail = function() {
        if ("user" == $scope.assignmentOption.id) {
            $scope.popup.assignmentObject.idm.assignee = {email: $scope.popup.email};
        } else if ("users" == $scope.assignmentOption.id) {

            // Only add if not yet part of candidate users
            var found = false;
            if ($scope.popup.assignmentObject.idm.candidateUsers) {
                for (var i = 0; i < $scope.popup.assignmentObject.idm.candidateUsers.length; i++) {

                    if ($scope.popup.assignmentObject.idm.candidateUsers[i].id) {
                        if ($scope.popup.assignmentObject.idm.candidateUsers[i].id === user.id) {
                            found = true;
                            break;
                        }
                    } else if ($scope.popup.assignmentObject.idm.candidateUsers[i].email) {
                        if ($scope.popup.assignmentObject.idm.candidateUsers[i].email === $scope.popup.email) {
                            found = true;
                            break;
                        }
                    }
                }
            }

            if (!found) {
                $scope.addCandidateUser({email: $scope.popup.email});
            }
        }
    };

    $scope.confirmGroup = function(group) {
        if (!group) {
            // Selection is done with keyboard, use selection index
            var groups = $scope.popup.groupResults;
            if ($scope.popup.selectedGroupIndex >= 0 && $scope.popup.selectedGroupIndex < groups.length) {
                group = groups[$scope.popup.selectedGroupIndex];
            }
        }

        if (group) {
            // Only add if not yet part of candidate groups
            var found = false;
            if ($scope.popup.assignmentObject.idm.candidateGroups) {
                for (var i = 0; i < $scope.popup.assignmentObject.idm.candidateGroups.length; i++) {
                    if ($scope.popup.assignmentObject.idm.candidateGroups[i].id === group.id) {
                        found = true;
                        break;
                    }
                }
            }

            if (!found) {
                $scope.addCandidateGroup(group);
            }
        }
    };

    $scope.addCandidateUser = function(user) {
        $scope.popup.assignmentObject.idm.candidateUsers.push(user);
    };
    
    $scope.removeCandidateUser = function(user) {
        var users = $scope.popup.assignmentObject.idm.candidateUsers;
        var indexToRemove = -1;
        for (var i = 0; i < users.length; i++) {
            if (user.id) {
                if (user.id === users[i].id) {
                    indexToRemove = i;
                    break;
                }
            } else {
                if (user.email === users[i].email) {
                    indexToRemove = i;
                    break;
                }
            }
        }
        if (indexToRemove >= 0) {
            users.splice(indexToRemove, 1);
        }
    };
    
    $scope.addCandidateGroup = function(group) {
        $scope.popup.assignmentObject.idm.candidateGroups.push(group);
    };
    
    $scope.removeCandidateGroup = function(group) {
        var groups = $scope.popup.assignmentObject.idm.candidateGroups;
        var indexToRemove = -1;
        for (var i = 0; i < groups.length; i++) {
            if (group.id == groups[i].id) {
                indexToRemove = i;
                break;
            }
        }
        if (indexToRemove >= 0) {
            groups.splice(indexToRemove, 1);
        }
    };

    $scope.resetSelection = function() {
        if ($scope.popup.userResults && $scope.popup.userResults.length > 0) {
            $scope.popup.selectedIndex = 0;
        } else {
            $scope.popup.selectedIndex = -1;
        }
    };

    $scope.nextUser = function() {
        var users = $scope.popup.userResults;
        if (users && users.length > 0 && $scope.popup.selectedIndex < users.length -1) {
            $scope.popup.selectedIndex += 1;
        }
    };

    $scope.previousUser = function() {
        var users = $scope.popup.userResults;
        if (users && users.length > 0 && $scope.popup.selectedIndex > 0) {
            $scope.popup.selectedIndex -= 1;
        }
    };

    $scope.resetGroupSelection = function() {
        if ($scope.popup.groupResults && $scope.popup.groupResults.length > 0) {
            $scope.popup.selectedGroupIndex = 0;
        } else {
            $scope.popup.selectedGroupIndex = -1;
        }
    };

    $scope.nextGroup = function() {
        var groups = $scope.popup.groupResults;
        if (groups && groups.length > 0 && $scope.popup.selectedGroupIndex < groups.length -1) {
            $scope.popup.selectedGroupIndex += 1;
        }
    };

    $scope.previousGroup = function() {
        var groups = $scope.popup.groupResults;
        if (groups && groups.length > 0 && $scope.popup.selectedGroupIndex > 0) {
            $scope.popup.selectedGroupIndex -= 1;
        }
    };

    $scope.removeAssignee = function() {
        $scope.popup.assignmentObject.idm.assignee = undefined;
    };
    
    // Click handler for + button after enum value
    $scope.addCandidateUserValue = function(index) {
        $scope.popup.assignmentObject.static.candidateUsers.splice(index + 1, 0, {value: ''});
    };

    // Click handler for - button after enum value
    $scope.removeCandidateUserValue = function(index) {
        $scope.popup.assignmentObject.static.candidateUsers.splice(index, 1);
    };

    // Click handler for + button after enum value
    $scope.addCandidateGroupValue = function(index) {
        $scope.popup.assignmentObject.static.candidateGroups.splice(index + 1, 0, {value: ''});
    };

    // Click handler for - button after enum value
    $scope.removeCandidateGroupValue = function(index) {
        $scope.popup.assignmentObject.static.candidateGroups.splice(index, 1);
    };
    
    $scope.setSearchType = function() {
        $scope.popup.assignmentObject.assignmentSourceType = 'search';
    };

    $scope.allSteps = EDITOR.UTIL.collectSortedElementsFromPrecedingElements($scope.selectedShape);

    $scope.save = function () {

        handleAssignmentInput($scope.popup.assignmentObject.static);

        $scope.assignment.type = $scope.popup.assignmentObject.type;

        if ('idm' === $scope.popup.assignmentObject.type) { // IDM
            $scope.popup.assignmentObject.static = undefined;

            //Construct an IDM object to be saved to the process model.
            var idm = {type: $scope.assignmentOption.id};
            if ('user' == idm.type) {
                if ($scope.popup.assignmentObject.idm.assignee) {
                    idm.assignee = $scope.popup.assignmentObject.idm.assignee;
                }
            } else if ('users' == idm.type) {
                if ($scope.popup.assignmentObject.idm.candidateUsers && $scope.popup.assignmentObject.idm.candidateUsers.length > 0) {
                    idm.candidateUsers = $scope.popup.assignmentObject.idm.candidateUsers;
                }
            } else if ('groups' == idm.type) {
                if ($scope.popup.assignmentObject.idm.candidateGroups && $scope.popup.assignmentObject.idm.candidateGroups.length > 0) {
                    idm.candidateGroups = $scope.popup.assignmentObject.idm.candidateGroups;
                }
            }
            $scope.assignment.idm = idm;
            $scope.assignment.assignee = undefined;
            $scope.assignment.candidateUsers = undefined;
            $scope.assignment.candidateGroups = undefined;

        }

        if ('static' === $scope.popup.assignmentObject.type) { // IDM
            $scope.popup.assignmentObject.idm = undefined;
            $scope.assignment.idm = undefined;
            $scope.assignment.assignee = $scope.popup.assignmentObject.static.assignee;
            $scope.assignment.candidateUsers = $scope.popup.assignmentObject.static.candidateUsers;
            $scope.assignment.candidateGroups = $scope.popup.assignmentObject.static.candidateGroups;
        }

        $scope.property.value = {};
        $scope.property.value.assignment = $scope.assignment;
        $scope.updatePropertyInModel($scope.property);
        $scope.close();
    };

    // Close button handler
    $scope.close = function() {
    	$scope.property.mode = 'read';
    	$scope.$hide();
    };

    var handleAssignmentInput = function ($assignment) {
    
        function isEmptyString(value) {
          return (value === undefined || value === null || value.trim().length === 0);
        }
    
        if (isEmptyString($assignment.assignee)){
          $assignment.assignee = undefined;
        }
        var toRemoveIndexes;
        var removedItems=0;
        var i = 0;
        if ($assignment.candidateUsers) {
          toRemoveIndexes = [];
          for (i = 0; i < $assignment.candidateUsers.length; i++) {
            if (isEmptyString($assignment.candidateUsers[i].value)) {
              toRemoveIndexes[toRemoveIndexes.length] = i;
            }
          }
    
          if (toRemoveIndexes.length == $assignment.candidateUsers.length) {
            $assignment.candidateUsers = undefined;
          } else {
             removedItems=0;
            for (i = 0; i < toRemoveIndexes.length; i++) {
              $assignment.candidateUsers.splice(toRemoveIndexes[i]-removedItems, 1);
              removedItems++;
            }
          }
        }
    
        if ($assignment.candidateGroups) {
          toRemoveIndexes = [];
          for (i = 0; i < $assignment.candidateGroups.length; i++) {
            if (isEmptyString($assignment.candidateGroups[i].value)) {
              toRemoveIndexes[toRemoveIndexes.length] = i;
            }
          }
    
          if (toRemoveIndexes.length == $assignment.candidateGroups.length) {
            $assignment.candidateGroups = undefined;
          } else {
             removedItems=0;
            for (i = 0; i < toRemoveIndexes.length; i++) {
              $assignment.candidateGroups.splice(toRemoveIndexes[i]-removedItems, 1);
              removedItems++;
            }
          }
        }
    };
    
    function initStaticContextForEditing($scope) {
        if (!$scope.popup.assignmentObject.static.candidateUsers || $scope.popup.assignmentObject.static.candidateUsers.length==0) {
          $scope.popup.assignmentObject.static.candidateUsers = [{value: ''}];
        }
        if (!$scope.popup.assignmentObject.static.candidateGroups || $scope.popup.assignmentObject.static.candidateGroups.length==0) {
          $scope.popup.assignmentObject.static.candidateGroups = [{value: ''}];
        }
    }
}]);
