// Copyright 2014 The Bazel Authors. All rights reserved.
//
// 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.devtools.build.lib.events;

import static java.nio.charset.StandardCharsets.ISO_8859_1;

import com.google.devtools.build.lib.util.Preconditions;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Objects;

import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;

/**
 * An event is a situation encountered by the build system that's worth
 * reporting: A 3-tuple of ({@link EventKind}, {@link Location}, message).
 */
@Immutable
public final class Event implements Serializable {
  private final EventKind kind;
  private final Location location;
  private final String message;

  /**
   * An alternative representation for message.
   * Exactly one of message or messageBytes will be non-null.
   * If messageBytes is non-null, then it contains the bytes
   * of the message, encoded using the platform's default charset.
   * We do this to avoid converting back and forth between Strings
   * and bytes.
   */
  private final byte[] messageBytes;

  @Nullable
  private final String tag;

  private final int hashCode;

  private Event(EventKind kind, @Nullable Location location, String message, @Nullable String tag) {
    this.kind = Preconditions.checkNotNull(kind);
    this.location = location;
    this.message = Preconditions.checkNotNull(message);
    this.messageBytes = null;
    this.tag = tag;
    this.hashCode = Objects.hash(kind, location, message, tag, Arrays.hashCode(messageBytes));
  }

  private Event(
      EventKind kind, @Nullable Location location, byte[] messageBytes, @Nullable String tag) {
    this.kind = Preconditions.checkNotNull(kind);
    this.location = location;
    this.message = null;
    this.messageBytes = Preconditions.checkNotNull(messageBytes);
    this.tag = tag;
    this.hashCode = Objects.hash(kind, location, message, tag, Arrays.hashCode(messageBytes));
  }

  public Event withTag(String tag) {
    if (this.message != null) {
      return new Event(this.kind, this.location, this.message, tag);
    } else {
      return new Event(this.kind, this.location, this.messageBytes, tag);
    }
  }

  public String getMessage() {
    return message != null ? message : new String(messageBytes);
  }

  public byte[] getMessageBytes() {
    return messageBytes != null ? messageBytes : message.getBytes(ISO_8859_1);
  }

  public EventKind getKind() {
    return kind;
  }

  /**
   * the tag is typically the action that generated the event.
   */
  @Nullable
  public String getTag() {
    return tag;
  }

  /**
   * Returns the location of this event, if any.  Returns null iff the event
   * wasn't associated with any particular location, for example, a progress
   * message.
   */
  @Nullable public Location getLocation() {
    return location;
  }

  /**
   * Returns <i>some</i> moderately sane representation of the event. Should never be used in
   * user-visible places, only for debugging and testing.
   */
  @Override
  public String toString() {
    return kind + " " + (location != null ? location.print() : "<no location>") + ": "
        + getMessage();
  }

  @Override
  public int hashCode() {
    return hashCode;
  }

  @Override
  public boolean equals(Object other) {
    if (other == this) {
      return true;
    }
    if (other == null || !other.getClass().equals(getClass())) {
      return false;
    }
    Event that = (Event) other;
    return Objects.equals(this.kind, that.kind)
        && Objects.equals(this.location, that.location)
        && Objects.equals(this.tag, that.tag)
        && Objects.equals(this.message, that.message)
        && Arrays.equals(this.messageBytes, that.messageBytes);
  }

  /**
   * Replay a sequence of events on an {@link EventHandler}.
   */
  public static void replayEventsOn(EventHandler eventHandler, Iterable<Event> events) {
    for (Event event : events) {
      eventHandler.handle(event);
    }
  }

  public static Event of(EventKind kind, @Nullable Location location, String message) {
    return new Event(kind, location, message, null);
  }

  public static Event of(EventKind kind, @Nullable Location location, byte[] messageBytes) {
    return new Event(kind, location, messageBytes, null);
  }

  /**
   * Reports a warning.
   */
  public static Event warn(@Nullable Location location, String message) {
    return new Event(EventKind.WARNING, location, message, null);
  }

  /**
   * Reports an error.
   */
  public static Event error(@Nullable Location location, String message){
    return new Event(EventKind.ERROR, location, message, null);
  }

  /**
   * Reports atemporal statements about the build, i.e. they're true for the duration of execution.
   */
  public static Event info(@Nullable Location location, String message) {
    return new Event(EventKind.INFO, location, message, null);
  }

  /**
   * Reports a temporal statement about the build.
   */
  public static Event progress(@Nullable Location location, String message) {
    return new Event(EventKind.PROGRESS, location, message, null);
  }

  /**
   * Reports a warning.
   */
  public static Event warn(String message) {
    return warn(null, message);
  }

  /**
   * Reports an error.
   */
  public static Event error(String message){
    return error(null, message);
  }

  /**
   * Reports atemporal statements about the build, i.e. they're true for the duration of execution.
   */
  public static Event info(String message) {
    return info(null, message);
  }

  /**
   * Reports a temporal statement about the build.
   */
  public static Event progress(String message) {
    return progress(null, message);
  }

}
