package com.hubspot.singularity;

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<String, SlaveMatchState> 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);
      }

    };
  }

  @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<String, SlaveMatchState> unmatchedOffers) {
    this.pendingTaskId = pendingTaskId;
    this.user = user;
    this.cmdLineArgsList = JavaUtils.nonNullImmutable(cmdLineArgsList);
    this.runId = runId;
    this.unmatchedOffers = unmatchedOffers == null ? new HashMap<String, SlaveMatchState>() : 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<String, SlaveMatchState> getUnmatchedOffers() {
    return unmatchedOffers;
  }

  public void addUnmatchedOffer(String host, SlaveMatchState reason) {
    unmatchedOffers.put(host, reason);
  }

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

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

}

@@ -27,16 +27,41 @@
 arity;%0A%0A
+import java.util.Arrays;%0A
 import j
@@ -645,32 +645,24 @@
 e final Map%3C
-String, 
 SlaveMatchSt
@@ -656,32 +656,46 @@
 %3CSlaveMatchState
+, List%3CString%3E
 %3E unmatchedOffer
@@ -1344,16 +1344,273 @@
 %7D;%0A  %7D%0A%0A
+  public SingularityPendingTask(SingularityPendingTaskId pendingTaskId, List%3CString%3E cmdLineArgsList, Optional%3CString%3E user, Optional%3CString%3E runId) %7B%0A    this(pendingTaskId, cmdLineArgsList, user, runId, new HashMap%3CSlaveMatchState, List%3CString%3E%3E());%0A  %7D%0A%0A
   @JsonC
@@ -1913,32 +1913,24 @@
 ffers%22) Map%3C
-String, 
 SlaveMatchSt
@@ -1932,16 +1932,30 @@
 tchState
+, List%3CString%3E
 %3E unmatc
@@ -2186,32 +2186,24 @@
 new HashMap%3C
-String, 
 SlaveMatchSt
@@ -2205,16 +2205,30 @@
 tchState
+, List%3CString%3E
 %3E() : un
@@ -2988,16 +2988,8 @@
 Map%3C
-String, 
 Slav
@@ -2999,16 +2999,30 @@
 tchState
+, List%3CString%3E
 %3E getUnm
@@ -3138,32 +3138,36 @@
 e reason) %7B%0A    
+if (
 unmatchedOffers.
@@ -3170,26 +3170,150 @@
 ers.
-put(host, reason);
+containsKey(reason)) %7B%0A      unmatchedOffers.get(reason).add(host);%0A    %7D else %7B%0A      unmatchedOffers.put(reason, Arrays.asList(host));%0A    %7D
 %0A  %7D

save list of hosts under each slave match state