/**
 * An element which displays a table of permissions on a repository and allows them to be
 * edited.
 */
angular.module('quay').filter('objectFilter', function() {
  return function(obj, filterFn) {
    if (!obj) { return []; }

    var result = [];
    angular.forEach(obj, function(value) {
      if (filterFn(value)) {
        result.push(value);
      }
    });

    return result;
  };
});

angular.module('quay').directive('repositoryPermissionsTable', function () {
  var directiveDefinitionObject = {
    priority: 0,
    templateUrl: '/static/directives/repository-permissions-table.html',
    replace: false,
    transclude: true,
    restrict: 'C',
    scope: {
      'repository': '=repository',
      'isEnabled': '=isEnabled'
    },
    controller: function($scope, $element, ApiService, Restangular, UtilService, RolesService) {
      $scope.permissionResources = {'team': {}, 'user': {}};
      $scope.permissionCache = {};
      $scope.permissions = {};

      var readRole = RolesService.repoRoles[0].id;

      $scope.addPermissionInfo = {
        'role': readRole
      };

      var loadAllPermissions = function() {
        if (!$scope.repository || !$scope.isEnabled) { return; }

        fetchPermissions('user');
        fetchPermissions('team');
      };

      var fetchPermissions = function(kind) {
        if ($scope.permissionResources[kind]['loading'] != null) {
          return;
        }

        var params = {
          'repository': $scope.repository.namespace + '/' + $scope.repository.name
        };

        var Kind = kind[0].toUpperCase() + kind.substring(1);
        var r = ApiService['listRepo' + Kind + 'PermissionsAsResource'](params).get(function(resp) {
          $scope.permissions[kind] = resp.permissions;
          return resp.permissions;
        });

        $scope.permissionResources[kind] = r;
      };

      $scope.$watch('repository', loadAllPermissions);
      $scope.$watch('isEnabled', loadAllPermissions);

      loadAllPermissions();

      var getPermissionEndpoint = function(entityName, kind) {
        var namespace = $scope.repository.namespace;
        var name = $scope.repository.name;
        var url = UtilService.getRestUrl('repository', namespace, name, 'permissions', kind, entityName);
        return Restangular.one(url);
      };

      $scope.buildEntityForPermission = function(permission, kind) {
        var key = permission.name + ':' + kind;
        if ($scope.permissionCache[key]) {
          return $scope.permissionCache[key];
        }

        return $scope.permissionCache[key] = {
          'kind': kind,
          'name': permission.name,
          'is_robot': permission.is_robot,
          'is_org_member': permission.is_org_member,
          'avatar': permission.avatar
        };
      };

      $scope.hasPermissions = function(teams, users) {
        if (teams && teams.value) {
          if (Object.keys(teams.value).length > 0) {
            return true;
          }
        }

        if (users && users.value) {
          if (Object.keys(users.value).length > 0) {
            return true;
          }
        }

        return false;
      };

      $scope.allEntries = function() {
        return true;
      };

      $scope.onlyRobot = function(permission) {
        return permission.is_robot == true;
      };

      $scope.onlyUser = function(permission) {
        return !permission.is_robot;
      };

      $scope.addPermission = function() {
        $scope.addPermissionInfo['working'] = true;
        $scope.addNewPermission($scope.addPermissionInfo.entity, $scope.addPermissionInfo.role)
      };

      $scope.grantPermission = function(entity, callback) {
        $scope.addRole(entity.name, 'read', entity.kind, callback);
      };

      $scope.addNewPermission = function(entity, opt_role) {
        // Don't allow duplicates.
        if (!entity || !entity.kind || $scope.permissions[entity.kind][entity.name]) {
          $scope.addPermissionInfo = {};
          return;
        }

        if (entity.is_org_member === false) {
          $scope.grantPermissionInfo = {
            'entity': entity
          };
          return;
        }

        $scope.addRole(entity.name, opt_role || 'read', entity.kind);
      };

      $scope.deleteRole = function(entityName, kind) {
        var errorHandler = ApiService.errorDisplay('Cannot change permission', function(resp) {
          if (resp.status == 409) {
            return 'Cannot change permission as you do not have the authority';
          }
        });

        var endpoint = getPermissionEndpoint(entityName, kind);
        endpoint.customDELETE().then(function() {
          delete $scope.permissions[kind][entityName];
        }, errorHandler);
      };

      $scope.addRole = function(entityName, role, kind, opt_callback) {
        var permission = {
          'role': role,
        };

        var errorHandler = ApiService.errorDisplay('Cannot change permission', function() {
          opt_callback && opt_callback(false);
          $scope.addPermissionInfo = {
            'role': readRole
          };
        });

        var endpoint = getPermissionEndpoint(entityName, kind);
        endpoint.customPUT(permission).then(function(result) {
          $scope.permissions[kind][entityName] = result;
          $scope.addPermissionInfo = {
            'role': readRole
          };
          opt_callback && opt_callback(true)
        }, errorHandler);
      };

      $scope.setRole = function(role, entityName, kind) {
        var errorDisplay = ApiService.errorDisplay(function(resp) {
          $scope.permissions[kind][entityName] = {'role': currentRole};
        });

        var permission = $scope.permissions[kind][entityName];
        var currentRole = permission.role;
        permission.role = role;

        var endpoint = getPermissionEndpoint(entityName, kind);
        endpoint.customPUT(permission).then(function() {}, errorDisplay);
      };
    }
  };
  return directiveDefinitionObject;
});