// Copyright (C) 2017 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.supermanifest;

import static com.google.gerrit.reviewdb.client.RefNames.REFS_HEADS;

import com.google.common.base.Strings;
import com.google.gerrit.reviewdb.client.Project;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Objects;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Repository;

class ConfigEntry {
  public static final String SECTION_NAME = "superproject";

  Project.NameKey srcRepoKey;
  String srcRef;
  URI baseUri;
  ToolType toolType;
  String xmlPath;
  Project.NameKey destRepoKey;
  boolean recordSubmoduleLabels;
  boolean ignoreRemoteFailures;

  // destBranch can be "*" in which case srcRef is ignored.
  String destBranch;

  ConfigEntry(Config cfg, String name) throws ConfigInvalidException {
    String[] parts = name.split(":");
    if (parts.length != 2) {
      throw new ConfigInvalidException(
          String.format("pluginName '%s' must have form REPO:BRANCH", name));
    }

    String destRepo = parts[0];
    String destRef = parts[1];

    if (!destRef.startsWith(REFS_HEADS)) {
      throw new ConfigInvalidException(
          String.format("invalid destination '%s'. Must specify refs/heads/", destRef));
    }

    if (destRef.contains("*") && !destRef.equals(REFS_HEADS + "*")) {
      throw new ConfigInvalidException(
          String.format("invalid destination '%s'. Use just '*' for all branches.", destRef));
    }

    String srcRepo = cfg.getString(SECTION_NAME, name, "srcRepo");
    if (srcRepo == null) {
      throw new ConfigInvalidException(String.format("entry %s did not specify srcRepo", name));
    }

    // TODO(hanwen): sanity check repo names.
    srcRepoKey = new Project.NameKey(srcRepo);

    String toolType = Strings.nullToEmpty(cfg.getString(SECTION_NAME, name, "toolType"));

    switch (toolType) {
      case "":
      case "repo":
        this.toolType = ToolType.Repo;
        break;
      case "jiri":
        this.toolType = ToolType.Jiri;
        break;
      default:
        throw new ConfigInvalidException(
            String.format("entry %s has invalid toolType: %s", name, toolType));
    }

    if (destRef.equals(REFS_HEADS + "*")) {
      srcRef = "";
    } else {
      if (!Repository.isValidRefName(destRef)) {
        throw new ConfigInvalidException(String.format("destination branch '%s' invalid", destRef));
      }

      srcRef = cfg.getString(SECTION_NAME, name, "srcRef");
      if (!Repository.isValidRefName(srcRef)) {
        throw new ConfigInvalidException(String.format("source ref '%s' invalid", srcRef));
      }

      if (srcRef == null) {
        throw new ConfigInvalidException(String.format("entry %s did not specify srcRef", name));
      }
    }

    xmlPath = cfg.getString(SECTION_NAME, name, "srcPath");
    if (xmlPath == null) {
      throw new ConfigInvalidException(String.format("entry %s did not specify srcPath", name));
    }

    destRepoKey = new Project.NameKey(destRepo);

    // The external format is chosen so we can support copying over tags as well.
    destBranch = destRef.substring(REFS_HEADS.length());

    recordSubmoduleLabels = cfg.getBoolean(SECTION_NAME, name, "recordSubmoduleLabels", false);
    ignoreRemoteFailures = cfg.getBoolean(SECTION_NAME, name, "ignoreRemoteFailures", false);

    try {
      // http://foo/platform/manifest => http://foo/platform/
      baseUri = new URI(srcRepoKey.toString()).resolve("");
    } catch (URISyntaxException exception) {
      throw new ConfigInvalidException("could not build src URL", exception);
    }
  }

  public String src() {
    String src = srcRef;
    if (destBranch.equals("*")) {
      src = "*";
    }
    return srcRepoKey + ":" + src + ":" + xmlPath;
  }

  public String dest() {
    return destRepoKey + ":" + destBranch;
  }

  @Override
  public String toString() {
    return String.format("%s (%s) => %s", src(), toolType, dest());
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    ConfigEntry that = (ConfigEntry) o;
    if (!destRepoKey.equals(that.destRepoKey)) return false;
    return destBranch.equals(that.destBranch);
  }

  @Override
  public int hashCode() {
    return Objects.hash(destRepoKey, destBranch);
  }

  /** @return the srcRepoKey */
  public Project.NameKey getSrcRepoKey() {
    return srcRepoKey;
  }

  /** @return the srcRef */
  public String getSrcRef() {
    return srcRef;
  }

  /** @return the baseUri */
  public URI getBaseUri() {
    return baseUri;
  }

  /** @return the toolType */
  public ToolType getToolType() {
    return toolType;
  }

  /** @return the xmlPath */
  public String getXmlPath() {
    return xmlPath;
  }

  /** @return the destRepoKey */
  public Project.NameKey getDestRepoKey() {
    return destRepoKey;
  }

  /** @return the recordSubmoduleLabels */
  public boolean isRecordSubmoduleLabels() {
    return recordSubmoduleLabels;
  }

  /** @return the destBranch */
  public String getDestBranch() {
    return destBranch;
  }

  enum ToolType {
    Repo,
    Jiri
  }
}
