/**
 * An element which displays a create entity dialog.
 */
angular.module('quay').directive('createEntityDialog', function () {
  var directiveDefinitionObject = {
    priority: 0,
    templateUrl: '/static/directives/create-entity-dialog.html',
    replace: false,
    transclude: true,
    restrict: 'C',
    scope: {
      'info': '=info',

      'entityKind': '@entityKind',
      'entityTitle': '@entityTitle',
      'entityIcon': '@entityIcon',
      'entityNameRegex': '@entityNameRegex',

      'entityCreateRequested': '&entityCreateRequested',
      'entityCreateCompleted': '&entityCreateCompleted'
    },

    controller: function($scope, $element, ApiService, UIService, TableService, RolesService, UserService) {
      $scope.TableService = TableService;

      $scope.options = {
        'predicate': 'last_modified_datetime',
        'reverse': false,
        'filter': ''
      };

      var handleRepoCheckChange = function() {
        $scope.repositories.forEach(function(repo) {
          if ($scope.checkedRepos.isChecked(repo)) {
            if (repo['permission'] == 'none') {
              repo['permission'] = 'read';
            }
          } else {
            repo['permission'] = 'none';
          }
        });
      };

      $scope.$on('$destroy', function() {
        if ($scope.inBody) {
          document.body.removeChild($element[0]);
        }
      });

      $scope.setRole = function(role, repo) {
        repo['permission'] = role;

        if (role == 'none') {
          $scope.checkedRepos.uncheckItem(repo);
        } else {
          $scope.checkedRepos.checkItem(repo);
        }
      };

      $scope.hide = function() {
        $element.find('.modal').modal('hide');
        if ($scope.entity) {
          $scope.entityCreateCompleted({'entity': $scope.entity});
          $scope.entity = null;
        }
      };

      $scope.show = function() {
        $scope.entityName = null;
        $scope.entity = null;
        $scope.creating = false;
        $scope.view = 'enterName';
        $scope.enterNameForm.$setPristine(true);

        // Move the dialog to the body to prevent it from nesting if called
        // from within another dialog.
        $element.find('.modal').modal({});
        $scope.inBody = true;
        document.body.appendChild($element[0]);
      };

      var setRepoState = function() {
        if (!$scope.repositories) {
          return;
        }

        $scope.orderedRepositories = TableService.buildOrderedItems($scope.repositories, $scope.options,
            ['name', 'permission'],
            ['last_modified_datetime']);
      };

      var entityCreateCallback = function(entity) {
        if (!entity || $scope.info.skip_permissions) {
          $scope.entity = entity;
          $scope.hide();
          return;
        }

        // Load the repositories under the entity's namespace.
        var params = {
          'namespace': $scope.info.namespace,
          'last_modified': true
        };

        ApiService.listRepos(null, params).then(function(resp) {
          $scope.view = 'addperms';
          $scope.entity = entity;

          var repos = [];
          resp['repositories'].forEach(function(repo) {
            repos.push({
              'namespace': repo.namespace,
              'name': repo.name,
              'last_modified': repo.last_modified,
              'last_modified_datetime': TableService.getReversedTimestamp(repo.last_modified),
              'permission': 'none'
            });
          });

          if (repos.length == 0) {
            $scope.hide();
            return;
          }

          $scope.repositories = repos;
          $scope.checkedRepos = UIService.createCheckStateController($scope.repositories, 'name');
          $scope.checkedRepos.listen(handleRepoCheckChange);

          if ($scope.info.repository) {
            repos.forEach(function(repo) {
              if (repo['namespace'] == $scope.info.repository.namespace &&
                  repo['name'] == $scope.info.repository.name) {
                $scope.checkedRepos.checkItem(repo);
                $scope.options.filter = $scope.info.repository.name;
              }
            });
          }

          setRepoState();
        }, ApiService.errorDisplay('Could not load repositories'));
      };

      $scope.addPermissions = function() {
        $scope.view = 'addingperms';

        var repos = $scope.checkedRepos.checked;
        var counter = 0;

        var addPerm = function() {
          if (counter >= repos.length) {
            $scope.hide();
            return;
          }

          var repo = repos[counter];
          RolesService.setRepositoryRole(repo, repo.permission, $scope.entityKind, $scope.entity.name,
            function(status) {
              if (status) {
                counter++;
                addPerm();
              } else {
                $scope.hide();
              }
            });
        };

        addPerm();
      };

      $scope.createEntity = function() {
        $scope.view = 'creating';
        $scope.entityCreateRequested({
          'name': $scope.entityName,
          'callback': entityCreateCallback
        });
      };

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

      $scope.noRepositoriesFilter = function(item) {
        return false;
      };

      $scope.missingPermsRepositoriesFilter = function(item) {
        return !item.perm;
      };

      $scope.$watch('options.predicate', setRepoState);
      $scope.$watch('options.reverse', setRepoState);
      $scope.$watch('options.filter', setRepoState);

      $scope.$watch('entityNameRegex', function(r) {
        if (r) {
          $scope.entityNameRegexObj = new RegExp(r);
        }
      });

      $scope.$watch('info', function(info) {
        if (!info || !info.namespace) {
          $scope.hide();
          return;
        }

        $scope.namespace = UserService.getNamespace(info.namespace);
        if ($scope.namespace) {
          $scope.show();
        }
      });
    }
  };
  return directiveDefinitionObject;
});