/*
 * Copyright 2013-present Facebook, 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.facebook.buck.rules;

import com.facebook.buck.event.AbstractBuckEvent;
import com.facebook.buck.event.BuckEvent;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;

/**
 * Base class for events about build rules.
 */
@SuppressWarnings("PMD.OverrideBothEqualsAndHashcode")
public abstract class BuildRuleEvent extends AbstractBuckEvent {
  private final BuildRule rule;

  protected BuildRuleEvent(BuildRule rule) {
    this.rule = rule;
  }

  public BuildRule getBuildRule() {
    return rule;
  }

  @Override
  public String getValueString() {
    return rule.getFullyQualifiedName();
  }

  @Override
  public boolean eventsArePair(BuckEvent event) {
    if (!(event instanceof BuildRuleEvent)) {
      return false;
    }

    return Objects.equal(getBuildRule(), ((BuildRuleEvent) event).getBuildRule());
  }

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

  public static Started started(BuildRule rule) {
    return new Started(rule);
  }

  public static Finished finished(BuildRule rule,
      BuildRuleStatus status,
      CacheResult cacheResult,
      Optional<BuildRuleSuccess.Type> successType) {
    return new Finished(rule, status, cacheResult, successType);
  }

  public static class Started extends BuildRuleEvent {
    protected Started(BuildRule rule) {
      super(rule);
    }

    @Override
    protected String getEventName() {
      return "BuildRuleStarted";
    }
  }

  public static class Finished extends BuildRuleEvent {
    private final BuildRuleStatus status;
    private final CacheResult cacheResult;
    private final Optional<BuildRuleSuccess.Type> successType;

    protected Finished(BuildRule rule,
        BuildRuleStatus status,
        CacheResult cacheResult,
        Optional<BuildRuleSuccess.Type> successType) {
      super(rule);
      this.status = Preconditions.checkNotNull(status);
      this.cacheResult = Preconditions.checkNotNull(cacheResult);
      this.successType = Preconditions.checkNotNull(successType);
    }

    public BuildRuleStatus getStatus() {
      return status;
    }

    public CacheResult getCacheResult() {
      return cacheResult;
    }

    public Optional<BuildRuleSuccess.Type> getSuccessType() {
      return successType;
    }

    @Override
    public String toString() {
      return String.format("BuildRuleFinished(%s): %s %s",
          getBuildRule(),
          getStatus(),
          getCacheResult());
    }

    @Override
    public boolean equals(Object o) {
      if (!super.equals(o)) {
        return false;
      }

      Finished that = (Finished)o;
      return Objects.equal(getStatus(), that.getStatus()) &&
          Objects.equal(getCacheResult(), that.getCacheResult()) &&
          Objects.equal(getSuccessType(), that.getSuccessType());
    }

    @Override
    public int hashCode() {
      return Objects.hashCode(getBuildRule(),
          getStatus(),
          getCacheResult(),
          getSuccessType());
    }

    @Override
    protected String getEventName() {
      return "BuildRuleFinished";
    }
  }

}

@@ -851,16 +851,45 @@
 tions;%0A%0A
+import java.io.IOException;%0A%0A
 /**%0A * B
@@ -2996,24 +2996,242 @@
 oString() %7B%0A
+      RuleKey ruleKey;%0A      try %7B%0A        ruleKey = getBuildRule().getRuleKey();%0A      %7D catch (IOException e) %7B%0A        throw new RuntimeException(%22RuleKey should already be computed if this is built.%22, e);%0A      %7D%0A%0A
       return
@@ -3268,16 +3268,19 @@
 hed(%25s):
+ %25s
  %25s %25s%22,
@@ -3321,32 +3321,32 @@
    getStatus(),%0A
-
           getCac
@@ -3355,16 +3355,35 @@
 Result()
+,%0A          ruleKey
 );%0A    %7D

Include the RuleKey when writing entries to build.log.