/*
 * Copyright 2014 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.dev.codeserver;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.TreeLogger.Type;
import com.google.gwt.dev.cfg.ModuleDef;
import com.google.gwt.dev.codeserver.JobEvent.CompileStrategy;
import com.google.gwt.dev.codeserver.JobEvent.Status;
import com.google.gwt.thirdparty.guava.common.base.Preconditions;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableList;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableSortedMap;
import com.google.gwt.thirdparty.guava.common.util.concurrent.Futures;
import com.google.gwt.thirdparty.guava.common.util.concurrent.ListenableFuture;
import com.google.gwt.thirdparty.guava.common.util.concurrent.SettableFuture;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * A request for Super Dev Mode to compile something.
 *
 * <p>Each job has a lifecycle where it goes through up to four states. See
 * {@link JobEvent.Status}.
 *
 * <p>Jobs are thread-safe.
 */
class Job {
  private static final ConcurrentMap<String, AtomicInteger> prefixToNextId =
      new ConcurrentHashMap<String, AtomicInteger>();

  // Primary key

  private final String id;

  // Input

  private final String inputModuleName;

  private final ImmutableSortedMap<String, String> bindingProperties;

  // Output

  private final SettableFuture<Result> result = SettableFuture.create();

  // Listeners

  private final Outbox outbox;
  private final RecompileListener recompileListener;
  private final JobChangeListener jobChangeListener;
  private final LogSupplier logSupplier;

  private JobEventTable table; // non-null when submitted

  // Miscellaneous

  private final ImmutableList<String> args;
  private final Set<String> tags;

  /**
   * The id to report to the recompile listener.
   */
  private int compileId = -1; // non-negative after the compile has started

  private CompileDir compileDir; // non-null after the compile has started
  private CompileStrategy compileStrategy; // non-null after the compile has started
  private String outputModuleName; // non-null after successful compile

  private Exception listenerFailure;

  /**
   * Creates a job to update an outbox.
   * @param bindingProperties  Properties that uniquely identify a permutation.
   *     (Otherwise, more than one permutation will be compiled.)
   * @param parentLogger  The parent of the logger that will be used for this job.
   */
  Job(Outbox box, Map<String, String> bindingProperties,
      TreeLogger parentLogger, Options options) {
    this.id = chooseNextId(box);
    this.outbox = box;
    this.inputModuleName = box.getInputModuleName();
    // TODO: we will use the binding properties to find or create the outbox,
    // then take binding properties from the outbox here.
    this.bindingProperties = ImmutableSortedMap.copyOf(bindingProperties);
    this.recompileListener = Preconditions.checkNotNull(options.getRecompileListener());
    this.jobChangeListener = Preconditions.checkNotNull(options.getJobChangeListener());
    this.args = Preconditions.checkNotNull(options.getArgs());
    this.tags = Preconditions.checkNotNull(options.getTags());
    this.logSupplier = new LogSupplier(parentLogger, id);
  }

  static boolean isValidJobId(String id) {
    return ModuleDef.isValidModuleName(id);
  }

  private static String chooseNextId(Outbox box) {
    String prefix = box.getId();
    prefixToNextId.putIfAbsent(prefix, new AtomicInteger(0));
    return prefix + "_" + prefixToNextId.get(prefix).getAndIncrement();
  }

  /**
   * A string uniquely identifying this job (within this process).
   *
   * <p>Note that the number doesn't have any particular relationship
   * with the output directory's name since jobs can be submitted out of order.
   */
  String getId() {
    return id;
  }

  /**
   * The module name that will be sent to the compiler.
   */
  String getInputModuleName() {
    return inputModuleName;
  }

  /**
   * The binding properties to use for this recompile.
   */
  ImmutableSortedMap<String, String> getBindingProperties() {
    return bindingProperties;
  }

  /**
   * The outbox that will serve the job's result (if successful).
   */
  Outbox getOutbox() {
    return outbox;
  }

  /**
   * Returns the logger for this job. (Creates it on first use.)
   */
  TreeLogger getLogger() {
    return logSupplier.get();
  }

  /**
   * Blocks until we have the result of this recompile.
   */
  Result waitForResult() {
    return Futures.getUnchecked(getFutureResult());
  }

  /**
   * Returns a Future that will contain the result of this recompile.
   */
  ListenableFuture<Result> getFutureResult() {
    return result;
  }

  Exception getListenerFailure() {
    return listenerFailure;
  }

  // === state transitions ===

  /**
   * Returns true if this job has been submitted to the JobRunner.
   * (That is, if {@link #onSubmitted} has ever been called.)
   */
  synchronized boolean wasSubmitted() {
    return table != null;
  }

  boolean isDone() {
    return result.isDone();
  }

  /**
   * Reports that this job has been submitted to the JobRunner.
   * Starts sending updates to the JobTable.
   * @throws IllegalStateException if the job was already started.
   */
  synchronized void onSubmitted(JobEventTable table) {
    if (wasSubmitted()) {
      throw new IllegalStateException("compile job has already started: " + id);
    }
    this.table = table;
    table.publish(makeEvent(Status.WAITING), getLogger());
  }

  /**
   * Reports that we started to compile the job.
   */
  synchronized void onStarted(int compileId, CompileDir compileDir) {
    if (table == null || !table.isActive(this)) {
      throw new IllegalStateException("compile job is not active: " + id);
    }
    this.compileId = compileId;
    this.compileDir = compileDir;

    try {
      recompileListener.startedCompile(inputModuleName, compileId, compileDir);
    } catch (Exception e) {
      getLogger().log(TreeLogger.Type.WARN, "recompile listener threw exception", e);
      listenerFailure = e;
    }

    publish(makeEvent(Status.COMPILING));
  }

  /**
   * Reports that this job has made progress while compiling.
   * @throws IllegalStateException if the job is not running.
   */
  synchronized void onProgress(String stepMessage) {
    checkIsCompiling("onProgress");
    publish(makeEvent(Status.COMPILING, stepMessage));
  }

  synchronized void setCompileStrategy(CompileStrategy strategy) {
    checkIsCompiling("setCompileStrategy");
    if (compileStrategy != null) {
      throw new IllegalStateException("setCompileStrategy can only be set once per job");
    }
    this.compileStrategy = strategy;
    // Not bothering to send an event just for this change, so it will be included
    // in the next event.
  }

  /**
   * Reports that this job has finished.
   * @throws IllegalStateException if the job is not running.
   */
  synchronized void onFinished(Result newResult) {
    if (table == null || !table.isActive(this)) {
      throw new IllegalStateException("compile job is not active: " + id);
    }

    // Report that we finished unless the listener messed up already.
    if (listenerFailure == null) {
      try {
        recompileListener.finishedCompile(inputModuleName, compileId, newResult.isOk());
      } catch (Exception e) {
        getLogger().log(TreeLogger.Type.WARN, "recompile listener threw exception", e);
        listenerFailure = e;
      }
    }

    result.set(newResult);
    outputModuleName = newResult.outputModuleName;
    if (newResult.isOk()) {
      publish(makeEvent(Status.SERVING));
    } else {
      publish(makeEvent(Status.ERROR));
    }
  }

  /**
   * Reports that this job's output is no longer available.
   */
  synchronized void onGone() {
    if (table == null || !table.isActive(this)) {
      throw new IllegalStateException("compile job is not active: " + id);
    }
    publish(makeEvent(Status.GONE));
  }

  private JobEvent makeEvent(Status status) {
    return makeEvent(status, null);
  }

  private JobEvent makeEvent(Status status, String message) {
    JobEvent.Builder out = new JobEvent.Builder();
    out.setJobId(getId());
    out.setInputModuleName(getInputModuleName());
    out.setBindings(getBindingProperties());
    out.setStatus(status);
    out.setMessage(message);
    out.setOutputModuleName(outputModuleName);
    out.setCompileDir(compileDir);
    out.setCompileStrategy(compileStrategy);
    out.setArguments(args);
    out.setTags(tags);
    return out.build();
  }

  /**
   * Makes an event visible externally.
   */
  private void publish(JobEvent event) {
    if (listenerFailure == null) {
      try {
        jobChangeListener.onJobChange(event);
      } catch (Exception e) {
        getLogger().log(Type.WARN, "JobChangeListener threw exception", e);
        listenerFailure = e;
      }
    }
    table.publish(event, getLogger());
  }

  private void checkIsCompiling(String methodName) {
    if (table == null || table.getPublishedEvent(this).getStatus() != Status.COMPILING) {
      throw new IllegalStateException(methodName + " called for a job that isn't compiling: " + id);
    }
  }

  /**
   * Creates a child logger on first use.
   */
  static class LogSupplier {
    private final TreeLogger parent;
    private final String jobId;
    private TreeLogger child;

    LogSupplier(TreeLogger parent, String jobId) {
      this.parent = parent;
      this.jobId = jobId;
    }

    synchronized TreeLogger get() {
      if (child == null) {
        child = parent.branch(Type.INFO, "Job " + jobId);
      }
      return child;
    }
  }

  /**
   * The result of a recompile.
   */
  static class Result {

    /**
     * non-null if successful
     */
    final CompileDir outputDir;

    /**
     * non-null if successful.
     */
    final String outputModuleName;

    /**
     * non-null for an error
     */
    final Throwable error;

    Result(CompileDir outputDir, String outputModuleName, Throwable error) {
      assert (outputDir == null) != (error == null);
      this.outputDir = outputDir;
      this.outputModuleName = outputModuleName;
      this.error = error;
    }

    boolean isOk() {
      return error == null;
    }
  }
}
