/*
 * 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.dev.cfg.ModuleDef;
import com.google.gwt.dev.cfg.ModuleDefSchema;
import com.google.gwt.dev.util.log.MetricName;
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.ImmutableMap;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableSortedMap;

import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.regex.Pattern;

/**
 * The status of a compile job submitted to Super Dev Mode.
 *
 * <p>JobEvent objects are deeply immutable, though they describe a Job that changes.
 */
public final class JobEvent {
  private static final Pattern VALID_TAG = Pattern.compile("^\\S{1,100}$");

  private final String jobId;

  private final String inputModuleName;
  private final ImmutableSortedMap<String, String> bindings;
  private final Status status;
  private final String message;

  private final String outputModuleName;
  private final CompileDir compileDir;
  private final CompileStrategy compileStrategy;
  private final ImmutableList<String> arguments;
  private final ImmutableList<String> tags;
  private final ImmutableSortedMap<String, Long> metricMap;

  private JobEvent(Builder builder) {
    this.jobId = Preconditions.checkNotNull(builder.jobId);
    this.inputModuleName = Preconditions.checkNotNull(builder.inputModuleName);
    this.bindings = ImmutableSortedMap.copyOf(builder.bindings);
    this.status = Preconditions.checkNotNull(builder.status);
    this.message = builder.message == null ? status.defaultMessage : builder.message;

    this.arguments = ImmutableList.copyOf(builder.args);
    this.tags = ImmutableList.copyOf(builder.tags);
    this.metricMap = ImmutableSortedMap.copyOf(builder.metricMap);

    // The following fields may be null.
    this.outputModuleName = builder.outputModuleName;
    this.compileDir = builder.compileDir;
    this.compileStrategy = builder.compileStrategy;

    // Any new fields added should allow nulls for backward compatibility.
  }

  /**
   * The id of the job being compiled. Unique within the same CodeServer process.
   * This should be considered an opaque string.
   */
  public String getJobId() {
    return jobId;
  }

  /**
   * The module name sent to the GWT compiler to start the compile.
   */
  public String getInputModuleName() {
    return inputModuleName;
  }

  /**
   * The binding properties sent to the GWT compiler.
   */
  public SortedMap<String, String> getBindings() {
    // Can't return ImmutableSortedMap here because it's repackaged and this is a public API.
    return bindings;
  }

  /**
   * The last reported status of the job.
   */
  public Status getStatus() {
    return status;
  }

  /**
   * Returns a line of text describing the job's current status.
   */
  public String getMessage() {
    return message;
  }

  /**
   * Returns the module name used for the output of the GWT compiler, or null if not available.
   * (This name is used for the name of the module directory, the nocache.js file, and in all
   * JavaScript generated by the GWT compiler.)
   * Only available for completed, successful compiles.
   */
  public String getOutputModuleName() {
    return outputModuleName;
  }

  /**
   * Returns the directory where the GWT module is being compiled, or null if not available.
   * (Not available for jobs that are WAITING.)
   */
  public CompileDir getCompileDir() {
    return compileDir;
  }

  /**
   * Returns the strategy used to perform the compile or null if not available.
   * (Normally available for finished compiles.)
   */
  public CompileStrategy getCompileStrategy() {
    return compileStrategy;
  }

  /**
   * The arguments passed to Super Dev Mode at startup, or null if not available.
   */
  public List<String> getArguments() {
    return arguments;
  }

  /**
   * User-defined tags associated with this job. (Not null but may be empty.)
   */
  public List<String> getTags() { return tags; }

  /**
   * Returns the amounts of performance-related metrics. (Not null but may be empty.)
   * The keys are subject to change.
   */
  public SortedMap<String, Long> getMetricMap() {
    // can't return ImmutableSortedMap because it's repackaged
    return metricMap;
  }

  /**
   * If all the given tags are valid, returns a list containing the tags.
   * @throws java.lang.IllegalArgumentException if any tag is invalid.
   */
  static ImmutableList<String> checkTags(Iterable<String> tags) {
    ImmutableList.Builder<String> builder = ImmutableList.builder();
    for (String tag : tags) {
      if (!isValidTag(tag)) {
        throw new IllegalArgumentException("invalid tag: " + tag);
      }
      builder.add(tag);
    }
    return builder.build();
  }

  /**
   * Returns true if the tag is valid.
   * Tags must not be null, contain whitespace, or be more than 100 characters.
   */
  private static boolean isValidTag(String candidate) {
    return candidate != null && VALID_TAG.matcher(candidate).matches();
  }

  /**
   * Defines the lifecycle of a job.
   */
  public enum Status {
    WAITING("waiting", "Waiting for the compiler to start"),
    COMPILING("compiling", "Compiling"),
    SERVING("serving", "Compiled output is ready"),
    GONE("gone", "Compiled output is no longer available"),
    ERROR("error", "Compile failed with an error");

    final String jsonName;
    final String defaultMessage;

    Status(String jsonName, String defaultMessage) {
      this.jsonName = jsonName;
      this.defaultMessage = defaultMessage;
    }
  }

  /**
   * The approach taken to do the compile.
   */
  public enum CompileStrategy {
    FULL("full"), // Compiled all the source.
    INCREMENTAL("incremental"), // Only recompiled the source files that changed.
    SKIPPED("skipped"); // Did not compile anything since nothing changed

    final String jsonName;

    CompileStrategy(String jsonName) {
      this.jsonName = jsonName;
    }

    /**
     * The string to use for serialization.
     */
    public String getJsonName() {
      return jsonName;
    }
  }

  /**
   * Creates a JobEvent.
   * This is public to allow external tests of code that implements {@link JobChangeListener}.
   * Normally all JobEvents are created in the code server.
   */
  public static class Builder {
    private String jobId;

    private String inputModuleName;
    private Map<String, String> bindings = ImmutableMap.of();
    private Status status;
    private String message;

    private List<String> args = ImmutableList.of();
    private List<String> tags = ImmutableList.of();
    private Map<String, Long> metricMap = ImmutableMap.of();

    private String outputModuleName;
    private CompileDir compileDir;
    private CompileStrategy compileStrategy;

    /**
     * A unique id for this job. Required.
     */
    public void setJobId(String jobId) {
      Preconditions.checkArgument(Job.isValidJobId(jobId), "invalid job id: " + jobId);
      this.jobId = jobId;
    }

    /**
     * The name of the module as passed to the compiler. Required.
     */
    public void setInputModuleName(String inputModuleName) {
      Preconditions.checkArgument(ModuleDef.isValidModuleName(inputModuleName),
          "invalid module name: " + jobId);
      this.inputModuleName = inputModuleName;
    }

    /**
     * The bindings passed to the compiler.
     * Optional, but may not be null. (Defaults to the empty map.)
     */
    public void setBindings(Map<String, String> bindings) {
      for (String name : bindings.keySet()) {
        if (!ModuleDefSchema.isValidPropertyName(name)) {
          throw new IllegalArgumentException("invalid property name: " + name);
        }
      }
      this.bindings = bindings;
    }

    /**
     * The job's current status. Required.
     */
    public void setStatus(Status status) {
      this.status = status;
    }

    /**
     * A message to describing the job's current state.
     * It should be a single line of text.
     * Optional. If null, a default message will be used.
     */
    public void setMessage(String message) {
      if (message != null) {
        Preconditions.checkArgument(!message.contains("\n"),
            "JobEvent messages should be a single line of text");
      }
      this.message = message;
    }

    /**
     * The module name that the compiler returned (after rename).
     */
    public void setOutputModuleName(String name) {
      this.outputModuleName = name;
    }

    /**
     * The directory where the GWT compiler will write its output.
     * Optional. (Not available until the compile starts.)
     */
    public void setCompileDir(CompileDir compileDir) {
      this.compileDir = compileDir;
    }

    /**
     * The strategy used to perform the compile.
     * Optional.
     */
    public void setCompileStrategy(CompileStrategy compileStrategy) {
      this.compileStrategy = compileStrategy;
    }

    /**
     * The arguments passed to {@link Options#parseArgs} at startup.
     * Optional but may not be null. If not set, defaults to the empty list.
     */
    public void setArguments(List<String> args) {
      this.args = Preconditions.checkNotNull(args);
    }

    /**
     * User-defined tags passed to {@link Options#addTags}.
     * Optional but may not be null. If not set, defaults to the empty list.
     */
    public void setTags(Iterable<String> tags) {
      this.tags = checkTags(tags);
    }

    /**
     * Sets a map containing metrics used for understanding compiler performance.
     * Optional but may not be null. If not set, defaults to the empty map.
     * Each key must be a valid identifier beginning with a capital letter.
     * (This constraint may be relaxed later.)
     */
    public void setMetricMap(Map<String, Long> nameToMetric) {
      for (String key : nameToMetric.keySet()) {
        // TODO: allow '.' in the key after making an API for that.
        Preconditions.checkArgument(MetricName.isValidKey(key),
            "invalid counter key: %s", key);
      }
      this.metricMap = nameToMetric;
    }

    public JobEvent build() {
      return new JobEvent(this);
    }
  }
}
