package com.amee.platform.resource.tag.v_3_0;

import com.amee.base.domain.Since;
import com.amee.base.resource.RequestWrapper;
import com.amee.base.resource.ResponseHelper;
import com.amee.base.transaction.AMEETransaction;
import com.amee.base.validation.ValidationException;
import com.amee.domain.IAMEEEntityReference;
import com.amee.domain.data.DataCategory;
import com.amee.domain.tag.EntityTag;
import com.amee.domain.tag.Tag;
import com.amee.platform.resource.tag.TagResourceService;
import com.amee.platform.resource.tag.TagValidationHelper;
import com.amee.platform.resource.tag.TagsResource;
import com.amee.service.auth.ResourceAuthorizationService;
import com.amee.service.data.DataService;
import com.amee.service.invalidation.InvalidationService;
import com.amee.service.tag.TagService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
@Scope("prototype")
@Since("3.0.0")
public class TagsFormAcceptor_3_0_0 implements TagsResource.FormAcceptor {

    private final Log log = LogFactory.getLog(getClass());

    @Autowired
    private InvalidationService invalidationService;

    @Autowired
    private TagService tagService;

    @Autowired
    private TagResourceService tagResourceService;

    @Autowired
    private TagValidationHelper validationHelper;

    @Autowired
    private ResourceAuthorizationService resourceAuthorizationService;

    @Override
    @AMEETransaction
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Object handle(RequestWrapper requestWrapper) throws ValidationException {
        Tag tag;
        // Get existing tag if it exists.
        Tag existingTag = tagService.getTagByTag(requestWrapper.getFormParameters().get("tag"));
        if (existingTag == null) {
            // Create new Tag.
            tag = new Tag();
            validationHelper.setTag(tag);
            if (validationHelper.isValid(requestWrapper.getFormParameters())) {
                // Save new Tag.
                log.debug("handle() Use new Tag.");
                // Authorized?
                resourceAuthorizationService.ensureAuthorizedForAccept(
                        requestWrapper.getAttributes().get("activeUserUid"));
                // Don't allow more than 1000 tags.
                // NOTE: See https://jira.amee.com/browse/PL-1761
                // Note: See https://jira.amee.com/browse/PL-1947
                if (tagService.getTagCount() >= 1000) {
                    throw new IllegalStateException("Only 1000 tags are allowed.");
                }
                // Save Tag.
                tagService.persist(tag);
            } else {
                throw new ValidationException(validationHelper.getValidationResult());
            }
        } else {
            // Use existing tag.
            log.debug("handle() Use existing Tag.");
            tag = existingTag;
        }
        // Deal with an entity if present.
        IAMEEEntityReference entity = tagResourceService.getEntity(requestWrapper);
        if (entity != null) {
            // TODO: Intention is to support entities other than DataCategory at some point.
            if (DataCategory.class.isAssignableFrom(entity.getClass())) {
                DataCategory dataCategory = (DataCategory) entity;
                // Authorized?
                resourceAuthorizationService.ensureAuthorizedForModify(
                        requestWrapper.getAttributes().get("activeUserUid"), dataCategory);
                // Find existing EntityTag.
                EntityTag entityTag = tagService.getEntityTag(dataCategory, tag.getTag());
                if (entityTag == null) {
                    // Create and save EntityTag.
                    log.debug("handle() Use new EntityTag.");
                    entityTag = new EntityTag(dataCategory, tag);
                    tagService.persist(entityTag);
                    // Need to invalidate the Data Category.
                    invalidationService.add(dataCategory);
                } else {
                    log.debug("handle() EntityTag already exists.");
                }
            } else {
                throw new IllegalStateException("Tags are currently only supported against DataCategories.");
            }
        } else {
            log.debug("handle() No entity.");
        }
        // Woo!
        return ResponseHelper.getOK(requestWrapper);
    }
}
@@ -1912,24 +1912,33 @@
    Tag tag;%0A
+        %0A
         // G
@@ -1967,16 +1967,16 @@
 exists.%0A
-
         
@@ -2091,32 +2091,45 @@
 gTag == null) %7B%0A
+            %0A
             // C
@@ -2286,32 +2286,49 @@
 arameters())) %7B%0A
+                %0A
                 
@@ -2388,32 +2388,49 @@
 Use new Tag.%22);%0A
+                %0A
                 
@@ -2590,24 +2590,41 @@
 UserUid%22));%0A
+                %0A
             
@@ -2945,32 +2945,49 @@
               %7D%0A
+                %0A
                 
@@ -3171,32 +3171,45 @@
        %7D else %7B%0A
+            %0A
             // U
@@ -3311,32 +3311,41 @@
 gTag;%0A        %7D%0A
+        %0A
         // Deal 
@@ -3477,32 +3477,45 @@
 tity != null) %7B%0A
+            %0A
             // T
@@ -3732,16 +3732,33 @@
 entity;%0A
+                %0A
         
@@ -3936,32 +3936,49 @@
  dataCategory);%0A
+                %0A
                 
@@ -4129,32 +4129,53 @@
 yTag == null) %7B%0A
+                    %0A
                 
@@ -4383,24 +4383,45 @@
 entityTag);%0A
+                    %0A
             
@@ -4850,32 +4850,41 @@
 y.%22);%0A        %7D%0A
+        %0A
         // Woo!%0A
@@ -4883,16 +4883,103 @@
 // Woo!%0A
+        String location = %22/%22 + requestWrapper.getVersion() + %22/tags/%22 + tag.getUid();%0A
         
@@ -5016,22 +5016,46 @@
 questWrapper
+, location, tag.getUid()
 );%0A    %7D%0A%7D

Set Location header when creating tag. PL-11244.