package jetbrains.mps.baseLanguage.unitTest.execution;

/*Generated by MPS */

import org.jetbrains.mps.annotations.Immutable;
import org.jetbrains.annotations.NotNull;
import org.junit.runner.Description;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;

/**
 * Serves as a message in a interprocess communication between junit client process and the original server mps process
 */
@Immutable
public final class TestRawEvent {
  private final TestRawKey myTestKey;
  private final long myMemoryUsage;
  private final long myTime;

  public TestRawEvent(@NotNull Description description) {
    // note: description.getTestClass() may be null (e.g. when failure indicates an issue with loading of test class)
    myTestKey = constructKeyFromDescription(description);
    Runtime runtime = Runtime.getRuntime();
    myMemoryUsage = runtime.totalMemory() - runtime.freeMemory();
    myTime = System.currentTimeMillis();
  }

  public TestRawEvent(@NotNull String testCaseFqName, @Nullable String testMethodFqName, long memoryUsage, long time) {
    myTestKey = constructKeyFromString(testCaseFqName, testMethodFqName);
    myMemoryUsage = memoryUsage;
    myTime = time;
  }

  private static TestRawKey constructKeyFromDescription(Description description) {
    String testCaseFqName = description.getClassName();
    String methodFqName = description.getMethodName();
    return constructKeyFromString(testCaseFqName, methodFqName);
  }

  private static TestRawKey constructKeyFromString(String testCaseFqName, @Nullable String testMethodFqName) {
    if (testMethodFqName != null) {
      return new TestMethodStringKey(testCaseFqName, testMethodFqName);
    }
    return new TestCaseStringKey(testCaseFqName);
  }

  @Override
  public String toString() {
    StringBuilder builder = new StringBuilder();
    builder.append(this.myTestKey);
    if (getTestMethodFqName() != null) {
      builder.append(':').append(getTestMethodFqName());
    }
    builder.append(":memory=").append(this.myMemoryUsage);
    builder.append(":time=").append(this.myTime);
    return builder.toString();
  }

  public String getTestCaseFqName() {
    return myTestKey.getTestCaseFqName();
  }

  @Nullable
  public String getTestMethodFqName() {
    if (myTestKey instanceof TestMethodStringKey) {
      return ((TestMethodStringKey) myTestKey).getTestMethodFqName();
    }
    return null;
  }

  @NotNull
  public TestRawKey getTestKey() {
    return myTestKey;
  }

  public long getMemoryUsage() {
    return myMemoryUsage;
  }

  public long getTime() {
    return myTime;
  }

  @Override
  public boolean equals(Object o) {
    if (o == null || !(o instanceof TestRawEvent)) {
      return false;
    }
    TestRawEvent event = (TestRawEvent) o;
    return Objects.equals(myTestKey, event.myTestKey);
  }

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