// 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.plugins.checks.db;

import static com.google.common.collect.ImmutableList.toImmutableList;

import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Streams;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.plugins.checks.Checker;
import com.google.gerrit.plugins.checks.CheckerCreation;
import com.google.gerrit.plugins.checks.CheckerUpdate;
import com.google.gerrit.plugins.checks.CheckerUuid;
import com.google.gerrit.plugins.checks.api.BlockingCondition;
import com.google.gerrit.plugins.checks.api.CheckerStatus;
import com.google.gerrit.reviewdb.client.Project;
import java.text.MessageFormat;
import java.util.Locale;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.util.StringUtils;

/**
 * A basic property of a checker.
 *
 * <p>Each property knows how to read and write its value from/to a JGit {@link Config} file.
 */
enum CheckerConfigEntry {
  /**
   * The UUID of a checker. This property is equivalent to {@link Checker#getUuid()}.
   *
   * <p>This is a mandatory property.
   */
  UUID("uuid") {
    @Override
    void readFromConfig(@Nullable CheckerUuid checkerUuid, Checker.Builder checker, Config config)
        throws ConfigInvalidException {
      String configUuid = config.getString(SECTION_NAME, null, super.keyName);
      if (configUuid == null) {
        throw new ConfigInvalidException(
            String.format(
                "%s.%s is not set in config file for checker %s",
                SECTION_NAME, super.keyName, checkerUuid));
      }
      if (checkerUuid != null && !configUuid.equals(checkerUuid.get())) {
        throw new ConfigInvalidException(
            String.format(
                "value of %s.%s=%s does not match expected checker UUID %s",
                SECTION_NAME, super.keyName, configUuid, checkerUuid));
      }
      checker.setUuid(
          CheckerUuid.tryParse(configUuid)
              .orElseThrow(
                  () ->
                      new ConfigInvalidException(
                          String.format(
                              "invalid UUID in %s.%s=%s",
                              SECTION_NAME, super.keyName, configUuid))));
    }

    @Override
    void initNewConfig(Config config, CheckerCreation checkerCreation) {
      config.setString(SECTION_NAME, null, super.keyName, checkerCreation.getCheckerUuid().get());
    }

    @Override
    void updateConfigValue(Config config, CheckerUpdate checkerUpdate) {
      // Do nothing. UUID is immutable.
    }
  },

  /**
   * The name of a checker. This property is equivalent to {@link Checker#getName()}.
   *
   * <p>It defaults to {@code null} if not set.
   */
  NAME("name") {
    @Override
    void readFromConfig(CheckerUuid checkerUuid, Checker.Builder checker, Config config) {
      String name = config.getString(SECTION_NAME, null, super.keyName);
      if (name != null) {
        checker.setName(name);
      }
    }

    @Override
    void initNewConfig(Config config, CheckerCreation checkerCreation) {
      // Do nothing. Name key will be set by updateConfigValue.
    }

    @Override
    void updateConfigValue(Config config, CheckerUpdate checkerUpdate) {
      checkerUpdate
          .getName()
          .ifPresent(
              name -> {
                if (!Strings.isNullOrEmpty(name)) {
                  config.setString(SECTION_NAME, null, super.keyName, name);
                } else {
                  config.unset(SECTION_NAME, null, super.keyName);
                }
              });
    }
  },

  /**
   * The description of a checker. This property is equivalent to {@link Checker#getDescription()}.
   *
   * <p>It defaults to {@code null} if not set.
   */
  DESCRIPTION("description") {
    @Override
    void readFromConfig(CheckerUuid checkerUuid, Checker.Builder checker, Config config) {
      String description = config.getString(SECTION_NAME, null, super.keyName);
      if (!Strings.isNullOrEmpty(description)) {
        checker.setDescription(description);
      }
    }

    @Override
    void initNewConfig(Config config, CheckerCreation checkerCreation) {
      // Do nothing. Description key will be set by updateConfigValue.
    }

    @Override
    void updateConfigValue(Config config, CheckerUpdate checkerUpdate) {
      checkerUpdate
          .getDescription()
          .ifPresent(
              description -> {
                if (Strings.isNullOrEmpty(description)) {
                  config.unset(SECTION_NAME, null, super.keyName);
                } else {
                  config.setString(SECTION_NAME, null, super.keyName, description);
                }
              });
    }
  },

  /**
   * The URL of a checker. This property is equivalent to {@link Checker#getUrl()}.
   *
   * <p>It defaults to {@code null} if not set.
   */
  URL("url") {
    @Override
    void readFromConfig(CheckerUuid checkerUuid, Checker.Builder checker, Config config) {
      String url = config.getString(SECTION_NAME, null, super.keyName);
      if (!Strings.isNullOrEmpty(url)) {
        checker.setUrl(url);
      }
    }

    @Override
    void initNewConfig(Config config, CheckerCreation checkerCreation) {
      // Do nothing. URL key will be set by updateConfigValue.
    }

    @Override
    void updateConfigValue(Config config, CheckerUpdate checkerUpdate) {
      checkerUpdate
          .getUrl()
          .ifPresent(
              url -> {
                if (Strings.isNullOrEmpty(url)) {
                  config.unset(SECTION_NAME, null, super.keyName);
                } else {
                  config.setString(SECTION_NAME, null, super.keyName, url);
                }
              });
    }
  },

  /**
   * The repository for which the checker applies. This property is equivalent to {@link
   * Checker#getRepository()}.
   *
   * <p>This is a mandatory property.
   */
  REPOSITORY("repository") {
    @Override
    void readFromConfig(CheckerUuid checkerUuid, Checker.Builder checker, Config config)
        throws ConfigInvalidException {
      String repository = config.getString(SECTION_NAME, null, super.keyName);
      // An empty repository is invalid in NoteDb; CheckerConfig will refuse to store it
      if (repository == null) {
        throw new ConfigInvalidException(
            String.format(
                "%s.%s is not set in config file for checker %s",
                SECTION_NAME, super.keyName, checkerUuid));
      }
      checker.setRepository(new Project.NameKey(repository));
    }

    @Override
    void initNewConfig(Config config, CheckerCreation checkerCreation) {
      String repository = checkerCreation.getRepository().get();
      config.setString(SECTION_NAME, null, super.keyName, repository);
    }

    @Override
    void updateConfigValue(Config config, CheckerUpdate checkerUpdate) {
      checkerUpdate
          .getRepository()
          .ifPresent(
              repository -> config.setString(SECTION_NAME, null, super.keyName, repository.get()));
    }
  },

  STATUS("status") {
    @Override
    void readFromConfig(CheckerUuid checkerUuid, Checker.Builder checker, Config config)
        throws ConfigInvalidException {
      String value = config.getString(SECTION_NAME, null, super.keyName);
      if (value == null) {
        throw new ConfigInvalidException(
            String.format(
                "%s.%s is not set in config file for checker %s",
                SECTION_NAME, super.keyName, checkerUuid));
      }
      try {
        checker.setStatus(config.getEnum(SECTION_NAME, null, super.keyName, CheckerStatus.ENABLED));
      } catch (IllegalArgumentException e) {
        throw new ConfigInvalidException(e.getMessage());
      }
    }

    @Override
    void initNewConfig(Config config, CheckerCreation checkerCreation) {
      // New checkers default to enabled.
      config.setEnum(SECTION_NAME, null, super.keyName, CheckerStatus.ENABLED);
    }

    @Override
    void updateConfigValue(Config config, CheckerUpdate checkerUpdate) {
      checkerUpdate
          .getStatus()
          .ifPresent(status -> config.setEnum(SECTION_NAME, null, super.keyName, status));
    }
  },

  BLOCKING_CONDITIONS("blocking") {
    @Override
    void readFromConfig(CheckerUuid checkerUuid, Checker.Builder checker, Config config)
        throws ConfigInvalidException {
      checker.setBlockingConditions(
          getEnumSet(config, SECTION_NAME, super.keyName, BlockingCondition.values()));
    }

    @Override
    void initNewConfig(Config config, CheckerCreation checkerCreation) {
      // Do nothing. Blocking conditions will be set by updateConfigValue.
    }

    @Override
    void updateConfigValue(Config config, CheckerUpdate checkerUpdate) {
      checkerUpdate
          .getBlockingConditions()
          .ifPresent(
              blockingConditions ->
                  setEnumList(config, SECTION_NAME, null, super.keyName, blockingConditions));
    }
  },

  QUERY("query") {
    @Override
    void readFromConfig(CheckerUuid checkerUuid, Checker.Builder checker, Config config) {
      String value = config.getString(SECTION_NAME, null, super.keyName);
      if (value != null) {
        checker.setQuery(value);
      }
    }

    @Override
    void initNewConfig(Config config, CheckerCreation checkerCreation) {
      config.setString(SECTION_NAME, null, super.keyName, "status:open");
    }

    @Override
    void updateConfigValue(Config config, CheckerUpdate checkerUpdate) {
      checkerUpdate
          .getQuery()
          .ifPresent(
              query -> {
                if (!Strings.isNullOrEmpty(query)) {
                  config.setString(SECTION_NAME, null, super.keyName, query);
                } else {
                  config.unset(SECTION_NAME, null, super.keyName);
                }
              });
    }
  };

  private static <T extends Enum<T>> ImmutableSortedSet<T> getEnumSet(
      Config config, String section, String name, T[] all) throws ConfigInvalidException {
    ImmutableSortedSet.Builder<T> enumBuilder = ImmutableSortedSet.naturalOrder();
    for (String value : config.getStringList(section, null, name)) {
      enumBuilder.add(resolveEnum(section, name, value, all));
    }
    return enumBuilder.build();
  }

  private static <T extends Enum<T>> T resolveEnum(
      String section, String name, String value, T[] all) throws ConfigInvalidException {
    // Match some resolution semantics of DefaultTypedConfigGetter#getEnum.
    // TODO(dborowitz): Sure would be nice if Config exposed this logic (or getEnumList) so we
    // didn't have to replicate it.
    value = value.replace(' ', '_');
    for (T e : all) {
      if (StringUtils.equalsIgnoreCase(e.name(), value)) {
        return e;
      }
    }
    throw new ConfigInvalidException(
        MessageFormat.format(JGitText.get().enumValueNotSupported2, section, name, value));
  }

  private static <T extends Enum<T>> void setEnumList(
      Config config, String section, @Nullable String subsection, String name, Iterable<T> values) {
    // Match semantics of Config#setEnum.
    ImmutableList<String> strings =
        Streams.stream(values)
            .map(v -> v.name().toLowerCase(Locale.ROOT).replace('_', ' '))
            .collect(toImmutableList());
    config.setStringList(section, subsection, name, strings);
  }

  private static final String SECTION_NAME = "checker";

  private final String keyName;

  CheckerConfigEntry(String keyName) {
    this.keyName = keyName;
  }

  /**
   * Reads the corresponding property of this {@code CheckerConfigEntry} from the given {@code
   * Config}. The read value is written to the corresponding property of {@code Checker.Builder}.
   *
   * @param checkerUuid the UUID of the checker (necessary for helpful error messages)
   * @param checker the {@code Checker.Builder} whose property value should be set
   * @param config the {@code Config} from which the value of the property should be read
   * @throws ConfigInvalidException if the property has an unexpected value
   */
  abstract void readFromConfig(CheckerUuid checkerUuid, Checker.Builder checker, Config config)
      throws ConfigInvalidException;

  /**
   * Initializes the corresponding property of this {@code CheckerConfigEntry} in the given {@code
   * Config}.
   *
   * <p>If the specified {@code CheckerCreation} has an entry for the property, that value is used.
   * If not, the default value for the property is set. In any case, an existing entry for the
   * property in the {@code Config} will be overwritten.
   *
   * @param config a new {@code Config}, typically without an entry for the property
   * @param checkerCreation an {@code CheckerCreation} detailing the initial value of mandatory
   *     checker properties
   */
  abstract void initNewConfig(Config config, CheckerCreation checkerCreation);

  /**
   * Updates the corresponding property of this {@code CheckerConfigEntry} in the given {@code
   * Config} if the {@code CheckerUpdate} mentions a modification.
   *
   * <p>This call is a no-op if the {@code CheckerUpdate} doesn't contain a modification for the
   * property.
   *
   * @param config a {@code Config} for which the property should be updated
   * @param checkerUpdate an {@code CheckerUpdate} detailing the modifications on a checker
   */
  abstract void updateConfigValue(Config config, CheckerUpdate checkerUpdate);
}
