// Copyright (C) 2016 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.googlesource.gerrit.plugins.automerger;

import com.google.common.base.Joiner;
import com.google.gerrit.extensions.api.GerritApi;
import com.google.gerrit.extensions.restapi.BinaryResult;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.re2j.Pattern;

import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yaml.snakeyaml.Yaml;

/** The loaded configuration stored in memory. */
public class LoadedConfig {
  private static final Logger log = LoggerFactory.getLogger(LoadedConfig.class);

  private final Map<String, Object> global;
  private final Map<String, Map<String, ?>> config;
  private final Map<String, String> defaultManifestInfo;
  private final Pattern blankMergePattern;
  private final Pattern alwaysBlankMergePattern;

  public LoadedConfig() {
    global = Collections.emptyMap();
    config = Collections.emptyMap();
    defaultManifestInfo = Collections.emptyMap();
    blankMergePattern = Pattern.compile("");
    alwaysBlankMergePattern = Pattern.compile("");
  }

  public LoadedConfig(
      GerritApi gApi,
      String configProject,
      String configProjectBranch,
      String configFilename,
      List<String> configOptionKeys)
      throws IOException, RestApiException {
    log.info(
        "Loading config file from project {} on branch {} and filename {}",
        configProject,
        configProjectBranch,
        configFilename);
    BinaryResult configFile =
        gApi.projects().name(configProject).branch(configProjectBranch).file(configFilename);
    String configFileString = configFile.asString();
    config = (Map<String, Map<String, ?>>) (new Yaml().load(configFileString));
    global = (Map<String, Object>) config.get("global");
    defaultManifestInfo = (Map<String, String>) global.get("manifest");

    blankMergePattern = getConfigPattern("blank_merge");
    alwaysBlankMergePattern = getConfigPattern("always_blank_merge");
    log.info("Finished syncing automerger config.");
  }

  /**
   * Checks to see if we should skip the change.
   *
   * <p>If the commit message matches the alwaysBlankMergePattern, always return true. If the commit
   * message matches the blankMergePattern and merge_all is false for this pair of branches, return
   * true.
   *
   * @param fromBranch Branch we are merging from.
   * @param toBranch Branch we are merging to.
   * @param commitMessage Commmit message of the original change.
   * @return Whether or not to merge with "-s ours".
   */
  public boolean isSkipMerge(String fromBranch, String toBranch, String commitMessage) {
    // If regex matches always_blank_merge (DO NOT MERGE ANYWHERE), skip.
    if (alwaysBlankMergePattern.matches(commitMessage)) {
      return true;
    }

    // If regex matches blank_merge (DO NOT MERGE), skip iff merge_all is false
    if (blankMergePattern.matches(commitMessage)) {
      Map<String, Object> mergePairConfig = getMergeConfig(fromBranch, toBranch);
      if (mergePairConfig != null) {
        boolean isMergeAll = (boolean) mergePairConfig.getOrDefault("merge_all", false);
        return !isMergeAll;
      }
    }
    return false;
  }

  /**
   * Gets the merge configuration for this branch.
   *
   * @param fromBranch Branch we are merging from.
   * @return A map of config keys to their values, or a map of "to branches" to a map of config keys
   *     to their values.
   */
  public Map<String, Object> getMergeConfig(String fromBranch) {
    return getBranches().get(fromBranch);
  }

  /**
   * Gets the merge configuration for a pair of branches.
   *
   * @param fromBranch Branch we are merging from.
   * @param toBranch Branch we are merging to.
   * @return Map of configuration keys to their values.
   */
  public Map<String, Object> getMergeConfig(String fromBranch, String toBranch) {
    Map<String, Object> fromBranchConfig = getBranches().get(fromBranch);
    if (fromBranchConfig == null) {
      return Collections.emptyMap();
    }
    return (Map<String, Object>) fromBranchConfig.get(toBranch);
  }

  /**
   * Gets all the branches and their configuration information.
   *
   * @return A map of from branches to their configuration maps.
   */
  public Map<String, Map<String, Object>> getBranches() {
    return (Map<String, Map<String, Object>>)
        config.getOrDefault("branches", Collections.<String, Map<String, Object>>emptyMap());
  }

  /**
   * Gets the global config.
   *
   * @return A map of configuration keys to their values.
   */
  public Map<String, Object> getGlobal() {
    return global;
  }

  /**
   * Gets the default manifest information.
   *
   * @return A map of configuration keys to their default values.
   */
  public Map<String, String> getDefaultManifestInfo() {
    return defaultManifestInfo;
  }

  /**
   * Gets the automerge label (i.e. what to vote -1 on when we hit a merge conflict)
   *
   * @return The automerge label (by default, the String "Verified").
   */
  public String getAutomergeLabel() {
    return (String) global.getOrDefault("automerge_label", "Verified");
  }

  /**
   * Gets the value of a global attribute.
   *
   * @param key A configuration key that is defined in the config.
   * @return The value of the global attribute
   */
  public Object getGlobalAttribute(String key) {
    return global.get(key);
  }

  /**
   * Gets the value of a global attribute, or the default value if it cannot be found.
   *
   * @param key A configuration key that is defined in the config.
   * @param def The default value if we cannot find it in the config.
   * @return The value of the global attribute, or the default value if it cannot be found.
   */
  public Object getGlobalAttributeOrDefault(String key, Object def) {
    return global.getOrDefault(key, def);
  }

  private Pattern getConfigPattern(String key) {
    Set<String> mergeStrings = new HashSet<>((List<String>) global.get(key));
    return Pattern.compile(Joiner.on("|").join(mergeStrings), Pattern.DOTALL);
  }
}
