package eu.bcvsolutions.idm.core.model.event.processor.tree;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Description;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import com.google.common.collect.ImmutableMap;

import eu.bcvsolutions.idm.core.api.domain.CoreResultCode;
import eu.bcvsolutions.idm.core.api.dto.IdmTreeNodeDto;
import eu.bcvsolutions.idm.core.api.dto.filter.IdmRoleTreeNodeFilter;
import eu.bcvsolutions.idm.core.api.event.CoreEventProcessor;
import eu.bcvsolutions.idm.core.api.event.DefaultEventResult;
import eu.bcvsolutions.idm.core.api.event.EntityEvent;
import eu.bcvsolutions.idm.core.api.event.EventResult;
import eu.bcvsolutions.idm.core.api.exception.AcceptedException;
import eu.bcvsolutions.idm.core.api.service.IdmRoleTreeNodeService;
import eu.bcvsolutions.idm.core.api.service.IdmTreeNodeService;
import eu.bcvsolutions.idm.core.exception.TreeNodeException;
import eu.bcvsolutions.idm.core.model.event.TreeNodeEvent.TreeNodeEventType;
import eu.bcvsolutions.idm.core.model.repository.IdmIdentityContractRepository;

/**
 * Deletes tree node - ensures referential integrity.
 * 
 * @author Radek Tomiška
 *
 */
@Component
@Description("Deletes tree node - ensures referential integrity")
public class TreeNodeDeleteProcessor extends CoreEventProcessor<IdmTreeNodeDto> {

	public static final String PROCESSOR_NAME = "tree-node-delete-processor";
	private final IdmTreeNodeService service;
	private final IdmRoleTreeNodeService roleTreeNodeService;
	
	@Autowired
	public TreeNodeDeleteProcessor(
			IdmTreeNodeService service,
			IdmIdentityContractRepository identityContractRepository,
			TreeNodeSaveProcessor saveProcessor,
			IdmRoleTreeNodeService roleTreeNodeService) {
		super(TreeNodeEventType.DELETE);
		//
		Assert.notNull(service);
		Assert.notNull(saveProcessor);
		Assert.notNull(identityContractRepository);
		Assert.notNull(roleTreeNodeService);
		//
		this.service = service;
		this.roleTreeNodeService = roleTreeNodeService;	
	}
	
	@Override
	public String getName() {
		return PROCESSOR_NAME;
	}
	
	@Override
	public EventResult<IdmTreeNodeDto> process(EntityEvent<IdmTreeNodeDto> event) {
		IdmTreeNodeDto treeNode = event.getContent();
		// remove related automatic roles
		IdmRoleTreeNodeFilter filter = new IdmRoleTreeNodeFilter();
		filter.setTreeNodeId(treeNode.getId());
		roleTreeNodeService.find(filter, null).forEach(roleTreeNode -> {
			try {
				roleTreeNodeService.delete(roleTreeNode);
			} catch (AcceptedException ex) {
				throw new TreeNodeException(CoreResultCode.TREE_NODE_DELETE_FAILED_HAS_ROLE, 
						ImmutableMap.of(
								"treeNode", treeNode.getName(),
								"roleTreeNode", roleTreeNode.getId()
								));
			}
		});
		//		
		service.deleteInternal(treeNode);
		//
		return new DefaultEventResult<>(event, this);
	}
}

@@ -1581,18 +1581,91 @@
 ervice;%0A
+%09private final IdmIdentityContractRepository identityContractRepository;%0A
 %09%0A
-
 %09@Autowi
@@ -1797,48 +1797,8 @@
 ry,%0A
-%09%09%09TreeNodeSaveProcessor saveProcessor,%0A
 %09%09%09I
@@ -1913,41 +1913,8 @@
 e);%0A
-%09%09Assert.notNull(saveProcessor);%0A
 %09%09As
@@ -2076,16 +2076,80 @@
 rvice;%09%0A
+%09%09this.identityContractRepository = identityContractRepository;%0A
 %09%7D%0A%09%0A%09@O
@@ -2305,16 +2305,16 @@
 vent) %7B%0A
-
 %09%09IdmTre
@@ -2353,16 +2353,241 @@
 tent();%0A
+%09%09//%0A%09%09if (identityContractRepository.countByWorkPosition_Id(treeNode.getId()) %3E 0) %7B%0A%09%09%09throw new TreeNodeException(CoreResultCode.TREE_NODE_DELETE_FAILED_HAS_CONTRACTS, ImmutableMap.of(%22treeNode%22, treeNode.getName()));%0A%09%09%7D%0A
 %09%09// rem

disable tree node deletion, when identity contract exists