package com.hubspot.singularity;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import javax.annotation.Nonnull;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.hubspot.mesos.JavaUtils;

public class SingularityPendingTask {

  private final SingularityPendingTaskId pendingTaskId;
  private final List<String> cmdLineArgsList;
  private final Optional<String> user;
  private final Optional<String> runId;
  private final Map<SlaveMatchState, List<String>> unmatchedOffers;

  public static Predicate<SingularityPendingTask> matchingRequest(final String requestId) {
    return new Predicate<SingularityPendingTask>() {

      @Override
      public boolean apply(@Nonnull SingularityPendingTask input) {
        return input.getPendingTaskId().getRequestId().equals(requestId);
      }

    };
  }

  public static Predicate<SingularityPendingTask> matchingDeploy(final String deployId) {
    return new Predicate<SingularityPendingTask>() {

      @Override
      public boolean apply(@Nonnull SingularityPendingTask input) {
        return input.getPendingTaskId().getDeployId().equals(deployId);
      }

    };
  }

  public SingularityPendingTask(SingularityPendingTaskId pendingTaskId, List<String> cmdLineArgsList, Optional<String> user, Optional<String> runId) {
    this(pendingTaskId, cmdLineArgsList, user, runId, new HashMap<SlaveMatchState, List<String>>());
  }

  @JsonCreator
  public SingularityPendingTask(@JsonProperty("pendingTaskId") SingularityPendingTaskId pendingTaskId, @JsonProperty("cmdLineArgsList") List<String> cmdLineArgsList,
      @JsonProperty("user") Optional<String> user, @JsonProperty("runId") Optional<String> runId, @JsonProperty("unmatchedOffers") Map<SlaveMatchState, List<String>> unmatchedOffers) {
    this.pendingTaskId = pendingTaskId;
    this.user = user;
    this.cmdLineArgsList = JavaUtils.nonNullImmutable(cmdLineArgsList);
    this.runId = runId;
    this.unmatchedOffers = unmatchedOffers == null ? new HashMap<SlaveMatchState, List<String>>() : unmatchedOffers;
  }

  @Override
  public int hashCode() {
    return Objects.hashCode(pendingTaskId);
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }
    if (obj == null) {
      return false;
    }
    if (getClass() != obj.getClass()) {
      return false;
    }
    SingularityPendingTask other = (SingularityPendingTask) obj;
    return Objects.equals(pendingTaskId, other.getPendingTaskId());
  }

  public Optional<String> getUser() {
    return user;
  }

  public SingularityPendingTaskId getPendingTaskId() {
    return pendingTaskId;
  }

  public List<String> getCmdLineArgsList() {
    return cmdLineArgsList;
  }

  public Optional<String> getRunId() {
    return runId;
  }

  public Map<SlaveMatchState, List<String>> getUnmatchedOffers() {
    return unmatchedOffers;
  }

  public void addUnmatchedOffer(String host, SlaveMatchState reason) {
    if (unmatchedOffers.containsKey(reason)) {
      if (!unmatchedOffers.get(reason).contains(host)) {
        unmatchedOffers.get(reason).add(host);
      }
    } else {
      List<String> hosts = new ArrayList<>();
      hosts.add(host);
      unmatchedOffers.put(reason, hosts);
    }
  }

  public void clearUnmatchedOffers() {
    unmatchedOffers.clear();
  }

  @Override
  public String toString() {
    return "SingularityPendingTask [pendingTaskId=" + pendingTaskId + ", cmdLineArgsList=" + cmdLineArgsList + ", user=" + user + ", runId=" + runId + ", unmatchedOffers=" + unmatchedOffers + "]";
  }

}

@@ -80,16 +80,42 @@
 Arrays;%0A
+import java.util.EnumMap;%0A
 import j
@@ -128,24 +128,24 @@
 il.HashMap;%0A
-
 import java.
@@ -699,16 +699,20 @@
 e final 
+Enum
 Map%3CSlav
@@ -1607,28 +1607,28 @@
  runId, new 
-Hash
+Enum
 Map%3CSlaveMat
@@ -1650,16 +1650,37 @@
 tring%3E%3E(
+SlaveMatchState.class
 ));%0A  %7D%0A
@@ -1992,16 +1992,20 @@
 ffers%22) 
+Enum
 Map%3CSlav
@@ -2265,20 +2265,20 @@
 l ? new 
-Hash
+Enum
 Map%3CSlav
@@ -2304,16 +2304,37 @@
 tring%3E%3E(
+SlaveMatchState.class
 ) : unma
@@ -3067,32 +3067,32 @@
 urn runId;%0A  %7D%0A%0A
-
   public Map%3CSla
@@ -3084,16 +3084,20 @@
  public 
+Enum
 Map%3CSlav

use EnumMap