/**
 * An element which adds a series of dialogs for performing operations for tags (adding, moving
 * deleting).
 */
angular.module('quay').directive('tagOperationsDialog', function () {
  var directiveDefinitionObject = {
    priority: 0,
    templateUrl: '/static/directives/tag-operations-dialog.html',
    replace: false,
    transclude: false,
    restrict: 'C',
    scope: {
      'repository': '=repository',
      'images': '=images',
      'actionHandler': '=actionHandler',

      'getImages': '&getImages',
      'tagChanged': '&tagChanged'
    },
    controller: function($scope, $element, $timeout, ApiService) {
      $scope.addingTag = false;
      $scope.imagesInternal = [];

      $scope.$watch('images', function(images) {
        if (!images) { return; }
        $scope.imagesInternal = images;
      });

      var markChanged = function(added, removed) {
        // Reload the repository and the images.
        $scope.repository.get().then(function(resp) {
          $scope.repository = resp;

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

          ApiService.listRepositoryImages(null, params).then(function(resp) {
            $scope.images = resp.images;

            // Note: We need the timeout here so that Angular can $digest the images change
            // on the parent scope before the tagChanged callback occurs.
            $timeout(function() {
              $scope.tagChanged({
                'data': { 'added': added, 'removed': removed }
              });
            }, 1);
          })
        });
      };

      $scope.isAnotherImageTag = function(image, tag) {
        if (!$scope.repository || !$scope.imagesInternal) { return; }

        var found = $scope.repository.tags[tag];
        if (found == null) { return false; }
        return found.image_id != image;
      };

      $scope.isOwnedTag = function(image, tag) {
        if (!$scope.repository || !$scope.imagesInternal) { return; }

        var found = $scope.repository.tags[tag];
        if (found == null) { return false; }
        return found.image_id == image;
      };

      $scope.createOrMoveTag = function(image, tag) {
        if (!$scope.repository.can_write) { return; }

        $scope.addingTag = true;

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

        var data = {
          'image': image
        };

        var errorHandler = ApiService.errorDisplay('Cannot create or move tag', function(resp) {
          $element.find('#createOrMoveTagModal').modal('hide');
        });

        ApiService.changeTagImage(data, params).then(function(resp) {
          $element.find('#createOrMoveTagModal').modal('hide');
          $scope.addingTag = false;
          markChanged([tag], []);
        }, errorHandler);
      };

      $scope.deleteMultipleTags = function(tags, callback) {
        var count = tags.length;
        var perform = function(index) {
          if (index >= count) {
            callback(true);
            markChanged([], tags);
            return;
          }

          var tag_info = tags[index];
          if (!tag_info) { return; }

          $scope.deleteTag(tag_info.name, function(result) {
            if (!result) {
              callback(false);
              return;
            }

            perform(index + 1);
          }, true);
        };

        perform(0);
      };

      $scope.deleteTag = function(tag, callback, opt_skipmarking) {
        if (!$scope.repository.can_write) { return; }

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

        var errorHandler = ApiService.errorDisplay('Cannot delete tag', callback);
        ApiService.deleteFullTag(null, params).then(function() {
          callback(true);
          !opt_skipmarking && markChanged([], [tag]);
        }, errorHandler);
      };

      $scope.revertTag = function(tag, image_id, callback) {
        if (!$scope.repository.can_write) { return; }

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

        var data = {
          'image': image_id
        };

        var errorHandler = ApiService.errorDisplay('Cannot revert tag', callback);
        ApiService.revertTag(data, params).then(function() {
          callback(true);
          markChanged([], [tag]);
        }, errorHandler);
      };

      var lazyLoadImages = function(callback) {
        if ($scope.imagesInternal.length) {
          callback();
          return;
        }

        var isLoading = true;
        $timeout(function() {
          if (isLoading) {
            $('#loadingImagesModal').modal({});
          }
        }, 500);

        var cb = function(images) {
          isLoading = false;
          $('#loadingImagesModal').modal('hide');
          $scope.imagesInternal = images;
          callback();
        };

        $scope.getImages({'callback': cb});
      };

      $scope.actionHandler = {
        'askDeleteTag': function(tag) {
          lazyLoadImages(function() {
            $scope.deleteTagInfo = {
              'tag': tag
            };
          });
        },

        'askDeleteMultipleTags': function(tags) {
          lazyLoadImages(function() {
            $scope.deleteMultipleTagsInfo = {
              'tags': tags
            };
          });
        },

        'askAddTag': function(image) {
          lazyLoadImages(function() {
            $scope.tagToCreate = '';
            $scope.toTagImage = image;
            $scope.addingTag = false;
            $scope.addTagForm.$setPristine();
            $element.find('#createOrMoveTagModal').modal('show');
          });
        },

        'askRevertTag': function(tag, image_id) {
          lazyLoadImages(function() {
            if (tag.image_id == image_id) {
              bootbox.alert('This is the current image for the tag');
              return;
            }

            $scope.revertTagInfo = {
              'tag': tag,
              'image_id': image_id
            };

            $element.find('#revertTagModal').modal('show');
          });
        }
      };
    }
  };
  return directiveDefinitionObject;
});
