/*******************************************************************************
 * Copyright (c) 2004, 2007 Boeing.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Boeing - initial API and implementation
 *******************************************************************************/
package org.eclipse.osee.ats.core.client.artifact;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.osee.ats.api.ai.IAtsActionableItem;
import org.eclipse.osee.ats.api.data.AtsArtifactTypes;
import org.eclipse.osee.ats.api.data.AtsAttributeTypes;
import org.eclipse.osee.ats.api.data.AtsRelationTypes;
import org.eclipse.osee.ats.api.workflow.IAtsAction;
import org.eclipse.osee.ats.api.workflow.IAtsTask;
import org.eclipse.osee.ats.api.workflow.IAtsTeamWorkflow;
import org.eclipse.osee.ats.core.client.internal.Activator;
import org.eclipse.osee.ats.core.client.internal.AtsClientService;
import org.eclipse.osee.ats.core.client.search.UserRelatedToAtsObjectSearch;
import org.eclipse.osee.ats.core.client.util.AtsUtilClient;
import org.eclipse.osee.ats.core.client.workflow.AbstractWorkflowArtifact;
import org.eclipse.osee.ats.core.util.AtsUtilCore;
import org.eclipse.osee.framework.core.data.IRelationType;
import org.eclipse.osee.framework.jdk.core.type.OseeCoreException;
import org.eclipse.osee.framework.jdk.core.util.Strings;
import org.eclipse.osee.framework.skynet.core.User;
import org.eclipse.osee.framework.skynet.core.artifact.Artifact;
import org.eclipse.osee.framework.skynet.core.artifact.ArtifactCheck;
import org.eclipse.osee.framework.skynet.core.artifact.search.ArtifactQuery;

/**
 * Check for certain conditions that must be met to delete an ATS object or User artifact.
 *
 * @author Donald G. Dunne
 */
public class AtsArtifactChecks extends ArtifactCheck {

   private static final List<Long> Admin_Only_Relation_Type_Ids =
      org.eclipse.osee.framework.jdk.core.util.Collections.getAggregate(
         AtsRelationTypes.TeamWorkflowToReview_Review.getGuid(), AtsRelationTypes.ActionToWorkflow_Action.getGuid());
   private static boolean deletionChecksEnabled = !AtsUtilCore.isInTest();

   @Override
   public IStatus isDeleteableRelation(Artifact artifact, IRelationType relationType) throws OseeCoreException {
      if (deletionChecksEnabled) {
         boolean isAtsAdmin = AtsUtilClient.isAtsAdmin();
         if (!isAtsAdmin && Admin_Only_Relation_Type_Ids.contains(relationType.getGuid())) {
            return createStatus(
               String.format("Deletion of relation type [%s] off artifact [%s] is only permitted by ATS Admin",
                  relationType, artifact));
         }
      }
      return Status.OK_STATUS;
   }

   @Override
   public IStatus isDeleteable(Collection<Artifact> artifacts) throws OseeCoreException {
      boolean isAtsAdmin = AtsUtilClient.isAtsAdmin();

      IStatus result = Status.OK_STATUS;

      if (deletionChecksEnabled) {
         Set<Artifact> allArtifacts = getAllArtifacts(artifacts, new HashSet<>());

         if (result.isOK()) {
            result = checkActionableItems(isAtsAdmin, allArtifacts);
         }

         if (result.isOK()) {
            result = checkTeamDefinitions(isAtsAdmin, allArtifacts);
         }

         if (result.isOK()) {
            result = checkAtsWorkDefinitions(isAtsAdmin, allArtifacts);
         }

         if (result.isOK()) {
            result = checkUsers(allArtifacts);
         }

         if (result.isOK()) {
            result = checkActions(isAtsAdmin, allArtifacts);
         }

         if (result.isOK()) {
            result = checkWorkPackages(isAtsAdmin, allArtifacts);
         }
      }

      return result;
   }

   // Get all artifacts and recurse down default hierarchy
   private Set<Artifact> getAllArtifacts(Collection<Artifact> artifacts, Set<Artifact> allArtifacts) {
      for (Artifact art : artifacts) {
         if (art.isOnBranch(AtsUtilCore.getAtsBranch())) {
            allArtifacts.addAll(art.getDescendants());
         }
      }
      return allArtifacts;
   }

   private IStatus checkActions(boolean isAtsAdmin, Collection<Artifact> artifacts) {
      for (Artifact art : artifacts) {
         if (!isAtsAdmin && isWorkflowOrAction(art) && !isTask(art)) {
            return createStatus(String.format("Deletion of [%s] is only permitted by ATS Admin; %s invalid",
               art.getArtifactTypeName(), art.toStringWithId()));
         }
         String error = isWorkflowOrActionPermittedByAnyone(art, artifacts);
         if (Strings.isValid(error)) {
            return createStatus(String.format("Deletion of artifact type [%s] object %s is not permitted. Error: [%s]",
               art.getArtifactTypeName(), art.toStringWithId(), error));
         }
      }
      return Status.OK_STATUS;
   }

   private String isWorkflowOrActionPermittedByAnyone(Artifact art, Collection<Artifact> allArtifacts) {
      if (art.isOfType(AtsArtifactTypes.Action)) {
         for (IAtsTeamWorkflow teamWf : AtsClientService.get().getWorkItemService().getTeams((IAtsAction) art)) {
            if (!allArtifacts.contains(teamWf)) {
               return String.format("Can't delete action %s without deleting workflow %s, use ATS World Editor",
                  art.toStringWithId(), teamWf.toStringWithId());
            }
         }
      }
      if (art.isOfType(AtsArtifactTypes.TeamWorkflow)) {
         IAtsTeamWorkflow teamWf = AtsClientService.get().getWorkItemFactory().getTeamWf(art);
         if (!allArtifacts.contains(teamWf.getParentAction())) {
            return String.format("Can't delete workflow %s without deleting action %s, use ATS World Editor",
               teamWf.toStringWithId(), teamWf.getParentAction().toStringWithId());
         }
      }
      return null;
   }

   private boolean isWorkflowOrAction(Artifact art) {
      return art instanceof AbstractWorkflowArtifact || art instanceof IAtsAction;
   }

   private boolean isTask(Artifact art) {
      return art instanceof IAtsTask;
   }

   private IStatus createStatus(String message) {
      return new Status(IStatus.ERROR, Activator.PLUGIN_ID, message);
   }

   private IStatus checkActionableItems(boolean isAtsAdmin, Collection<Artifact> artifacts) throws OseeCoreException {
      Set<String> aiaGuids = getActionableItemGuidsWithRecurse(new HashSet<String>(), artifacts);
      if (!aiaGuids.isEmpty()) {
         List<Artifact> teamWfsRelatedToAis = ArtifactQuery.getArtifactListFromTypeAndAttribute(
            AtsArtifactTypes.TeamWorkflow, AtsAttributeTypes.ActionableItem, aiaGuids, AtsUtilCore.getAtsBranch(), 10);
         if (!teamWfsRelatedToAis.isEmpty()) {
            return createStatus(String.format(
               "Actionable Items (or children AIs) [%s] selected to delete have related Team Workflows; Delete or re-assign Team Workflows first.",
               aiaGuids));
         }
         if (!isAtsAdmin) {
            return createStatus("Deletion of Actionable Items is only permitted by ATS Admin.");
         }
      }
      return Status.OK_STATUS;
   }

   private Set<String> getActionableItemGuidsWithRecurse(HashSet<String> aiaGuids, Collection<Artifact> artifacts) {
      for (Artifact art : artifacts) {
         if (art.isOfType(AtsArtifactTypes.ActionableItem)) {
            IAtsActionableItem aia =
               AtsClientService.get().getCache().getByUuid(art.getUuid(), IAtsActionableItem.class);
            if (aia != null) {
               aiaGuids.add(AtsUtilCore.getGuid(aia));
               Collection<Artifact> childArts = art.getChildren();
               if (!aia.getChildrenActionableItems().isEmpty()) {
                  getActionableItemGuidsWithRecurse(aiaGuids, childArts);
               }
            }
         }
      }
      return aiaGuids;
   }

   private IStatus checkTeamDefinitions(boolean isAtsAdmin, Collection<Artifact> artifacts) throws OseeCoreException {
      List<String> guids = new ArrayList<>();
      for (Artifact art : artifacts) {
         if (art.isOfType(AtsArtifactTypes.TeamDefinition)) {
            guids.add(art.getGuid());
         }
      }
      if (!guids.isEmpty()) {
         List<Artifact> artifactListFromIds = ArtifactQuery.getArtifactListFromAttributeValues(
            AtsAttributeTypes.TeamDefinition, guids, AtsUtilCore.getAtsBranch(), 5);
         if (artifactListFromIds.size() > 0) {
            return createStatus(String.format(
               "Team Definition (or children Team Definitions) [%s] selected to delete have related Team Workflows; Delete or re-assign Team Workflows first.",
               guids));
         }
         if (!isAtsAdmin) {
            return createStatus("Deletion of Team Definitions is only permitted by ATS Admin.");
         }
      }
      return Status.OK_STATUS;
   }

   private IStatus checkWorkPackages(boolean isAtsAdmin, Collection<Artifact> artifacts) throws OseeCoreException {
      List<String> guids = new ArrayList<>();
      for (Artifact art : artifacts) {
         if (art.isOfType(AtsArtifactTypes.WorkPackage)) {
            guids.add(art.getGuid());
         }
      }
      if (!guids.isEmpty()) {
         List<Artifact> artifactListFromIds = ArtifactQuery.getArtifactListFromAttributeValues(
            AtsAttributeTypes.WorkPackageGuid, guids, AtsUtilCore.getAtsBranch(), 5);
         if (artifactListFromIds.size() > 0) {
            return createStatus(String.format(
               "Work Packages [%s] selected to delete have related Work Items; Delete or re-assign Work Packages first.",
               guids));
         }
      }
      return Status.OK_STATUS;
   }

   private IStatus checkAtsWorkDefinitions(boolean isAtsAdmin, Collection<Artifact> artifacts) throws OseeCoreException {
      for (Artifact art : artifacts) {
         if (art.isOfType(AtsArtifactTypes.WorkDefinition)) {
            List<Artifact> artifactListFromTypeAndAttribute =
               ArtifactQuery.getArtifactListFromTypeAndAttribute(AtsArtifactTypes.WorkDefinition,
                  AtsAttributeTypes.WorkflowDefinition, art.getName(), AtsUtilCore.getAtsBranch());
            if (artifactListFromTypeAndAttribute.size() > 0) {
               return createStatus(String.format(
                  "ATS WorkDefinition [%s] selected to delete has ats.WorkDefinition attributes set to it's name in %d artifact.  These must be changed first.",
                  art, artifactListFromTypeAndAttribute.size()));
            }
            if (!isAtsAdmin) {
               return createStatus("Deletion of Work Definitions is only permitted by ATS Admin.");
            }
         }
      }
      return Status.OK_STATUS;
   }

   private IStatus checkUsers(Collection<Artifact> artifacts) throws OseeCoreException {
      Set<User> users = new HashSet<>();
      for (Artifact art : artifacts) {
         if (art instanceof User) {
            users.add((User) art);
         }
      }
      for (User user : users) {
         UserRelatedToAtsObjectSearch srch = new UserRelatedToAtsObjectSearch(
            AtsClientService.get().getUserServiceClient().getUserFromOseeUser(user), false);
         if (srch.getResults().size() > 0) {
            return createStatus(String.format(
               "User name: \"%s\" userId: \"%s\" selected to delete has related ATS Objects; Un-relate to ATS first before deleting.",
               user.getName(), user.getUserId()));
         }
      }
      return Status.OK_STATUS;
   }

   public static void setDeletionChecksEnabled(boolean deletionChecksEnabled) {
      AtsArtifactChecks.deletionChecksEnabled = deletionChecksEnabled;
   }
}