// Copyright (C) 2019 The Android Open Source Project
//
// 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.gerrit.server.logging;

import com.google.auto.value.AutoValue;
import com.google.common.base.MoreObjects;
import com.google.common.base.MoreObjects.ToStringHelper;
import com.google.common.collect.ImmutableList;
import com.google.common.flogger.LazyArg;
import com.google.common.flogger.LazyArgs;
import com.google.gerrit.common.Nullable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Optional;

/** Metadata that is provided to {@link PerformanceLogger}s as context for performance records. */
@AutoValue
public abstract class Metadata {
  /** The numeric ID of an account. */
  public abstract Optional<Integer> accountId();

  /**
   * The type of an action (ACCOUNT_UPDATE, CHANGE_UPDATE, GROUP_UPDATE, INDEX_QUERY,
   * PLUGIN_UPDATE).
   */
  public abstract Optional<String> actionType();

  /** An authentication domain name. */
  public abstract Optional<String> authDomainName();

  /** The name of a branch. */
  public abstract Optional<String> branchName();

  /** Key of an entity in a cache. */
  public abstract Optional<String> cacheKey();

  /** The name of a cache. */
  public abstract Optional<String> cacheName();

  /** The name of the implementation class. */
  public abstract Optional<String> className();

  /** The numeric ID of a change. */
  public abstract Optional<Integer> changeId();

  /**
   * The type of change ID which the user used to identify a change (e.g. numeric ID, triplet etc.).
   */
  public abstract Optional<String> changeIdType();

  /** The cause of an error. */
  public abstract Optional<String> cause();

  /** Side where the comment is written: <= 0 for parent, 1 for revision. */
  public abstract Optional<Integer> commentSide();

  /** The SHA1 of a commit. */
  public abstract Optional<String> commit();

  /** Diff algorithm used in diff computation. */
  public abstract Optional<String> diffAlgorithm();

  /** The type of an event. */
  public abstract Optional<String> eventType();

  /** The value of the @Export annotation which was used to register a plugin extension. */
  public abstract Optional<String> exportValue();

  /** Path of a file in a repository. */
  public abstract Optional<String> filePath();

  /** Garbage collector name. */
  public abstract Optional<String> garbageCollectorName();

  /** Git operation (CLONE, FETCH). */
  public abstract Optional<String> gitOperation();

  /** The numeric ID of an internal group. */
  public abstract Optional<Integer> groupId();

  /** The name of a group. */
  public abstract Optional<String> groupName();

  /** The UUID of a group. */
  public abstract Optional<String> groupUuid();

  /** HTTP status response code. */
  public abstract Optional<Integer> httpStatus();

  /** The name of a secondary index. */
  public abstract Optional<String> indexName();

  /** The version of a secondary index. */
  public abstract Optional<Integer> indexVersion();

  /** The name of the implementation method. */
  public abstract Optional<String> memoryPoolName();

  /** The name of the implementation method. */
  public abstract Optional<String> methodName();

  /** One or more resources */
  public abstract Optional<Boolean> multiple();

  /** The name of an operation that is performed. */
  public abstract Optional<String> operationName();

  /** Partial or full computation */
  public abstract Optional<Boolean> partial();

  /** If a value is still current or not */
  public abstract Optional<Boolean> outdated();

  /** Path of a metadata file in NoteDb. */
  public abstract Optional<String> noteDbFilePath();

  /** Name of a metadata ref in NoteDb. */
  public abstract Optional<String> noteDbRefName();

  /** Type of a sequence in NoteDb (ACCOUNTS, CHANGES, GROUPS). */
  public abstract Optional<String> noteDbSequenceType();

  /** The ID of a patch set. */
  public abstract Optional<Integer> patchSetId();

  /** Plugin metadata that doesn't fit into any other category. */
  public abstract ImmutableList<PluginMetadata> pluginMetadata();

  /** The name of a plugin. */
  public abstract Optional<String> pluginName();

  /** The name of a Gerrit project (aka Git repository). */
  public abstract Optional<String> projectName();

  /** The type of a Git push to Gerrit (CREATE_REPLACE, NORMAL, AUTOCLOSE). */
  public abstract Optional<String> pushType();

  /** The number of resources that is processed. */
  public abstract Optional<Integer> resourceCount();

  /** The name of a REST view. */
  public abstract Optional<String> restViewName();

  /** The SHA1 of Git commit. */
  public abstract Optional<String> revision();

  /** The username of an account. */
  public abstract Optional<String> username();

  /**
   * Returns a string representation of this instance that is suitable for logging. This is wrapped
   * in a {@link LazyArg} because it is expensive to evaluate.
   *
   * <p>{@link #toString()} formats the {@link Optional} fields as {@code key=Optional[value]} or
   * {@code key=Optional.empty}. Since this class has many optional fields from which usually only a
   * few are populated this leads to long string representations such as
   *
   * <pre>
   * Metadata{accountId=Optional.empty, actionType=Optional.empty, authDomainName=Optional.empty,
   * branchName=Optional.empty, cacheKey=Optional.empty, cacheName=Optional.empty,
   * className=Optional.empty, changeId=Optional[9212550], changeIdType=Optional.empty,
   * cause=Optional.empty, eventType=Optional.empty, exportValue=Optional.empty,
   * filePath=Optional.empty, garbageCollectorName=Optional.empty, gitOperation=Optional.empty,
   * groupId=Optional.empty, groupName=Optional.empty, groupUuid=Optional.empty,
   * httpStatus=Optional.empty, indexName=Optional.empty, indexVersion=Optional[0],
   * methodName=Optional.empty, multiple=Optional.empty, operationName=Optional.empty,
   * partial=Optional.empty, noteDbFilePath=Optional.empty, noteDbRefName=Optional.empty,
   * noteDbSequenceType=Optional.empty, patchSetId=Optional.empty, pluginMetadata=[],
   * pluginName=Optional.empty, projectName=Optional.empty, pushType=Optional.empty,
   * resourceCount=Optional.empty, restViewName=Optional.empty, revision=Optional.empty,
   * username=Optional.empty}
   * </pre>
   *
   * <p>That's hard to read in logs. This is why this method
   *
   * <ul>
   *   <li>drops fields which have {@code Optional.empty} as value and
   *   <li>reformats values that are {@code Optional[value]} to {@code value}.
   * </ul>
   *
   * <p>For the example given above the formatted string would look like this:
   *
   * <pre>
   * Metadata{changeId=9212550, indexVersion=0, pluginMetadata=[]}
   * </pre>
   *
   * @return string representation of this instance that is suitable for logging
   */
  LazyArg<String> toStringForLoggingLazy() {
    // Don't use a lambda because different compilers generate different method names for lambdas,
    // e.g. "lambda$myFunction$0" vs. just "lambda$0" in Eclipse. We need to identify the method
    // by name to skip it and avoid infinite recursion.
    return LazyArgs.lazy(this::toStringForLoggingImpl);
  }

  private String toStringForLoggingImpl() {
    // Append class name.
    String className = getClass().getSimpleName();
    if (className.startsWith("AutoValue_")) {
      className = className.substring(10);
    }
    ToStringHelper stringHelper = MoreObjects.toStringHelper(className);

    // Append key-value pairs for field which are set.
    Method[] methods = Metadata.class.getDeclaredMethods();
    Arrays.sort(methods, Comparator.comparing(Method::getName));
    for (Method method : methods) {
      if (Modifier.isStatic(method.getModifiers())) {
        // skip static method
        continue;
      }

      if (method.getName().equals("toStringForLoggingLazy")
          || method.getName().equals("toStringForLoggingImpl")) {
        // Don't call myself in infinite recursion.
        continue;
      }

      if (method.getReturnType().equals(Void.TYPE) || method.getParameterCount() > 0) {
        // skip method since it's not a getter
        continue;
      }

      method.setAccessible(true);

      Object returnValue;
      try {
        returnValue = method.invoke(this);
      } catch (IllegalArgumentException | IllegalAccessException | InvocationTargetException e) {
        // should never happen
        throw new IllegalStateException(e);
      }

      if (returnValue instanceof Optional) {
        Optional<?> fieldValueOptional = (Optional<?>) returnValue;
        if (!fieldValueOptional.isPresent()) {
          // drop this key-value pair
          continue;
        }

        // format as 'key=value' instead of 'key=Optional[value]'
        stringHelper.add(method.getName(), fieldValueOptional.get());
      } else {
        // not an Optional value, keep as is
        stringHelper.add(method.getName(), returnValue);
      }
    }

    return stringHelper.toString();
  }

  public static Metadata.Builder builder() {
    return new AutoValue_Metadata.Builder();
  }

  public static Metadata empty() {
    return builder().build();
  }

  @AutoValue.Builder
  public abstract static class Builder {
    public abstract Builder accountId(int accountId);

    public abstract Builder actionType(@Nullable String actionType);

    public abstract Builder authDomainName(@Nullable String authDomainName);

    public abstract Builder branchName(@Nullable String branchName);

    public abstract Builder cacheKey(@Nullable String cacheKey);

    public abstract Builder cacheName(@Nullable String cacheName);

    public abstract Builder className(@Nullable String className);

    public abstract Builder changeId(int changeId);

    public abstract Builder changeIdType(@Nullable String changeIdType);

    public abstract Builder cause(@Nullable String cause);

    public abstract Builder commentSide(int side);

    public abstract Builder commit(@Nullable String commit);

    public abstract Builder diffAlgorithm(@Nullable String diffAlgorithm);

    public abstract Builder eventType(@Nullable String eventType);

    public abstract Builder exportValue(@Nullable String exportValue);

    public abstract Builder filePath(@Nullable String filePath);

    public abstract Builder garbageCollectorName(@Nullable String garbageCollectorName);

    public abstract Builder gitOperation(@Nullable String gitOperation);

    public abstract Builder groupId(int groupId);

    public abstract Builder groupName(@Nullable String groupName);

    public abstract Builder groupUuid(@Nullable String groupUuid);

    public abstract Builder httpStatus(int httpStatus);

    public abstract Builder indexName(@Nullable String indexName);

    public abstract Builder indexVersion(int indexVersion);

    public abstract Builder memoryPoolName(@Nullable String memoryPoolName);

    public abstract Builder methodName(@Nullable String methodName);

    public abstract Builder multiple(boolean multiple);

    public abstract Builder operationName(String operationName);

    public abstract Builder partial(boolean partial);

    public abstract Builder outdated(boolean outdated);

    public abstract Builder noteDbFilePath(@Nullable String noteDbFilePath);

    public abstract Builder noteDbRefName(@Nullable String noteDbRefName);

    public abstract Builder noteDbSequenceType(@Nullable String noteDbSequenceType);

    public abstract Builder patchSetId(int patchSetId);

    abstract ImmutableList.Builder<PluginMetadata> pluginMetadataBuilder();

    public Builder addPluginMetadata(PluginMetadata pluginMetadata) {
      pluginMetadataBuilder().add(pluginMetadata);
      return this;
    }

    public abstract Builder pluginName(@Nullable String pluginName);

    public abstract Builder projectName(@Nullable String projectName);

    public abstract Builder pushType(@Nullable String pushType);

    public abstract Builder resourceCount(int resourceCount);

    public abstract Builder restViewName(@Nullable String restViewName);

    public abstract Builder revision(@Nullable String revision);

    public abstract Builder username(@Nullable String username);

    public abstract Metadata build();
  }
}
