package com.hubspot.blazar.base;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.Optional;
import com.hubspot.rosetta.annotations.StoredAsJson;

import java.util.Objects;

public class Build {
  public enum State {
    QUEUED(false), LAUNCHING(false), IN_PROGRESS(false), SUCCEEDED(true), CANCELLED(true), FAILED(true);

    private final boolean completed;

    State(boolean completed) {
      this.completed = completed;
    }

    public boolean isComplete() {
      return completed;
    }
  }

  private final Optional<Long> id;
  private final int moduleId;
  private final int buildNumber;
  private final State state;
  private final Optional<Long> startTimestamp;
  private final Optional<Long> endTimestamp;
  private final Optional<String> sha;
  @StoredAsJson
  private final Optional<CommitInfo> commitInfo;
  private final Optional<String> log;
  @StoredAsJson
  private final Optional<BuildConfig> buildConfig;
  @StoredAsJson
  private final Optional<BuildConfig> resolvedConfig;

  @JsonCreator
  public Build(@JsonProperty("id") Optional<Long> id,
               @JsonProperty("moduleId") int moduleId,
               @JsonProperty("buildNumber") int buildNumber,
               @JsonProperty("state") State state,
               @JsonProperty("startTimestamp") Optional<Long> startTimestamp,
               @JsonProperty("endTimestamp") Optional<Long> endTimestamp,
               @JsonProperty("sha") Optional<String> sha,
               @JsonProperty("commitInfo") Optional<CommitInfo> commitInfo,
               @JsonProperty("log") Optional<String> log,
               @JsonProperty("buildConfig") Optional<BuildConfig> buildConfig,
               @JsonProperty("resolvedConfig") Optional<BuildConfig> resolvedConfig) {
    this.id = id;
    this.moduleId = moduleId;
    this.buildNumber = buildNumber;
    this.state = state;
    this.startTimestamp = startTimestamp;
    this.endTimestamp = endTimestamp;
    this.sha = sha;
    this.commitInfo = com.google.common.base.Objects.firstNonNull(commitInfo, Optional.<CommitInfo>absent());
    this.log = log;
    this.buildConfig = buildConfig;
    this.resolvedConfig = resolvedConfig;
  }

  public static Build queuedBuild(Module module, int buildNumber) {
    Optional<Long> absentLong = Optional.absent();
    Optional<String> absentString = Optional.absent();
    Optional<CommitInfo> commitInfo = Optional.absent();
    Optional<BuildConfig> config = Optional.absent();

    return new Build(absentLong, module.getId().get(), buildNumber, State.QUEUED, absentLong, absentLong, absentString, commitInfo, absentString, config, config);
  }

  public Optional<Long> getId() {
    return id;
  }

  public int getModuleId() {
    return moduleId;
  }

  public int getBuildNumber() {
    return buildNumber;
  }

  public State getState() {
    return state;
  }

  public Optional<Long> getStartTimestamp() {
    return startTimestamp;
  }

  public Optional<Long> getEndTimestamp() {
    return endTimestamp;
  }

  public Optional<String> getSha() {
    return sha;
  }

  public Optional<CommitInfo> getCommitInfo() {
    return commitInfo;
  }

  public Optional<String> getLog() {
    return log;
  }

  public Optional<BuildConfig> getBuildConfig() {
    return buildConfig;
  }

  public Optional<BuildConfig> getResolvedConfig() {
    return resolvedConfig;
  }

  public Build withId(long id) {
    return new Build(Optional.of(id), moduleId, buildNumber, state, startTimestamp, endTimestamp, sha, commitInfo, log, buildConfig, resolvedConfig);
  }

  public Build withCommitInfo(CommitInfo commitInfo) {
    Optional<String> sha = Optional.of(commitInfo.getCurrent().getId());
    return new Build(id, moduleId, buildNumber, state, startTimestamp, endTimestamp, sha, Optional.of(commitInfo), log, buildConfig, resolvedConfig);
  }

  public Build withState(State state) {
    return new Build(id, moduleId, buildNumber, state, startTimestamp, endTimestamp, sha, commitInfo, log, buildConfig, resolvedConfig);
  }

  public Build withStartTimestamp(long startTimestamp) {
    return new Build(id, moduleId, buildNumber, state, Optional.of(startTimestamp), endTimestamp, sha, commitInfo, log, buildConfig, resolvedConfig);
  }

  public Build withEndTimestamp(long endTimestamp) {
    return new Build(id, moduleId, buildNumber, state, startTimestamp, Optional.of(endTimestamp), sha, commitInfo, log, buildConfig, resolvedConfig);
  }

  public Build withLog(String log) {
    return new Build(id, moduleId, buildNumber, state, startTimestamp, endTimestamp, sha, commitInfo, Optional.of(log), buildConfig, resolvedConfig);
  }

  public Build withBuildConfig(BuildConfig buildConfig) {
    return new Build(id, moduleId, buildNumber, state, startTimestamp, endTimestamp, sha, commitInfo, log, Optional.of(buildConfig), resolvedConfig);
  }

  public Build withResolvedConfig(BuildConfig resolvedConfig) {
    return new Build(id, moduleId, buildNumber, state, startTimestamp, endTimestamp, sha, commitInfo, log, buildConfig, Optional.of(resolvedConfig));
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }

    if (o == null || getClass() != o.getClass()) {
      return false;
    }

    Build build = (Build) o;
    return Objects.equals(moduleId, build.moduleId) && Objects.equals(buildNumber, build.buildNumber);
  }

  @Override
  public int hashCode() {
    return Objects.hash(moduleId, buildNumber);
  }
}

@@ -943,16 +943,57 @@
 g%3E log;%0A
+  private final Optional%3CString%3E taskId;%0A
   @Store
@@ -1702,16 +1702,80 @@
 g%3E log,%0A
+               @JsonProperty(%22taskId%22) Optional%3CString%3E taskId,%0A
         
@@ -2140,16 +2140,42 @@
  = sha;%0A
+    this.taskId = taskId;%0A
     this
@@ -2810,16 +2810,30 @@
 tString,
+ absentString,
  config,
@@ -3404,32 +3404,96 @@
 eturn log;%0A  %7D%0A%0A
+  public Optional%3CString%3E getTaskId() %7B%0A    return taskId;%0A  %7D%0A%0A
   public Optiona
@@ -3784,32 +3784,40 @@
 commitInfo, log,
+ taskId,
  buildConfig, re
@@ -4079,24 +4079,32 @@
 tInfo), log,
+ taskId,
  buildConfig
@@ -4265,32 +4265,40 @@
 commitInfo, log,
+ taskId,
  buildConfig, re
@@ -4485,32 +4485,40 @@
 commitInfo, log,
+ taskId,
  buildConfig, re
@@ -4701,32 +4701,40 @@
 commitInfo, log,
+ taskId,
  buildConfig, re
@@ -4909,16 +4909,24 @@
 of(log),
+ taskId,
  buildCo
@@ -5117,16 +5117,24 @@
 fo, log,
+ taskId,
  Optiona
@@ -5344,16 +5344,24 @@
 fo, log,
+ taskId,
  buildCo

Create taskId field for executor to report singularity task id into