// 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.google.gerrit.server.account.externalids;

import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.auto.value.AutoValue;
import com.google.auto.value.extension.memoized.Memoized;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
import com.google.common.hash.Hashing;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Account;
import com.google.gerrit.extensions.client.AuthType;
import java.io.Serializable;
import java.util.Collection;
import java.util.Locale;
import java.util.Objects;
import java.util.Optional;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;

@AutoValue
public abstract class ExternalId implements Serializable {
  // If these regular expressions are modified the same modifications should be done to the
  // corresponding regular expressions in the
  // com.google.gerrit.client.account.UsernameField class.
  private static final String USER_NAME_PATTERN_FIRST_REGEX = "[a-zA-Z0-9]";
  private static final String USER_NAME_PATTERN_REST_REGEX = "[a-zA-Z0-9.!#$%&’*+=?^_`\\{|\\}~@-]";
  private static final String USER_NAME_PATTERN_LAST_REGEX = "[a-zA-Z0-9]";

  /** Regular expression that a username must match. */
  private static final String USER_NAME_PATTERN_REGEX =
      "^("
          + //
          USER_NAME_PATTERN_FIRST_REGEX
          + //
          USER_NAME_PATTERN_REST_REGEX
          + "*"
          + //
          USER_NAME_PATTERN_LAST_REGEX
          + //
          "|"
          + //
          USER_NAME_PATTERN_FIRST_REGEX
          + //
          ")$";

  private static final Pattern USER_NAME_PATTERN = Pattern.compile(USER_NAME_PATTERN_REGEX);

  public static boolean isValidUsername(String username) {
    return USER_NAME_PATTERN.matcher(username).matches();
  }

  /**
   * Returns the ID of the first external ID from the provided external IDs that has the {@link
   * ExternalId#SCHEME_USERNAME} scheme.
   *
   * @param extIds external IDs
   * @return the ID of the first external ID from the provided external IDs that has the {@link
   *     ExternalId#SCHEME_USERNAME} scheme
   */
  public static Optional<String> getUserName(Collection<ExternalId> extIds) {
    return extIds.stream()
        .filter(e -> e.isScheme(SCHEME_USERNAME))
        .map(e -> e.key().id())
        .filter(u -> !Strings.isNullOrEmpty(u))
        .findFirst();
  }

  /**
   * Returns all emails of the provided external IDs as a distinct stream.
   *
   * @param extIds external IDs
   * @return distinct stream of all emails of the provided external IDs
   */
  public static Stream<String> getEmails(Collection<ExternalId> extIds) {
    return extIds.stream().map(e -> e.email()).filter(Objects::nonNull).distinct();
  }

  private static final long serialVersionUID = 1L;

  public static final String EXTERNAL_ID_SECTION = "externalId";
  public static final String ACCOUNT_ID_KEY = "accountId";
  public static final String EMAIL_KEY = "email";
  public static final String PASSWORD_KEY = "password";

  /**
   * Scheme used to label accounts created, when using the LDAP-based authentication types {@link
   * AuthType#LDAP}, {@link AuthType#CLIENT_SSL_CERT_LDAP}, {@link AuthType#HTTP_LDAP}, and {@link
   * AuthType#LDAP_BIND}. The external ID stores the username. Accounts with such an external ID
   * will be authenticated against the configured LDAP identity provider.
   *
   * <p>The name {@code gerrit:} was a very poor choice.
   *
   * <p>Scheme names must not contain colons (':').
   *
   * <p>Will be handled case insensitive, if auth.userNameCaseInsensitive = true.
   */
  public static final String SCHEME_GERRIT = "gerrit";

  /** Scheme used for randomly created identities constructed by a UUID. */
  public static final String SCHEME_UUID = "uuid";

  /** Scheme used to represent only an email address. */
  public static final String SCHEME_MAILTO = "mailto";

  /**
   * Scheme for the username used to authenticate an account, e.g. over SSH.
   *
   * <p>Will be handled case insensitive, if auth.userNameCaseInsensitive = true.
   */
  public static final String SCHEME_USERNAME = "username";

  /** Scheme used for GPG public keys. */
  public static final String SCHEME_GPGKEY = "gpgkey";

  /** Scheme for imported accounts from other servers with different GerritServerId */
  public static final String SCHEME_IMPORTED = "imported";

  /** Scheme for external auth used during authentication, e.g. OAuth Token */
  public static final String SCHEME_EXTERNAL = "external";

  /** Scheme for http resources. OpenID in particular makes use of these external IDs. */
  public static final String SCHEME_HTTP = "http";

  /** Scheme for https resources. OpenID in particular makes use of these external IDs. */
  public static final String SCHEME_HTTPS = "https";

  /** Scheme for xri resources. OpenID in particular makes use of these external IDs. */
  public static final String SCHEME_XRI = "xri";

  /** Scheme for Google OAuth external IDs. */
  public static final String SCHEME_GOOGLE_OAUTH = "google-oauth";

  @AutoValue
  public abstract static class Key implements Serializable {
    private static final long serialVersionUID = 1L;

    /**
     * Creates an external ID key.
     *
     * @param scheme the scheme name, must not contain colons (':'), can be {@code null}
     * @param id the external ID, must not contain colons (':')
     * @param isCaseInsensitive whether the external ID key is matched case insensitively
     * @return the created external ID key
     */
    @VisibleForTesting
    public static Key create(@Nullable String scheme, String id, boolean isCaseInsensitive) {
      return new AutoValue_ExternalId_Key(Strings.emptyToNull(scheme), id, isCaseInsensitive);
    }

    /**
     * Parses an external ID key from a string in the format "scheme:id" or "id".
     *
     * @return the parsed external ID key
     */
    public static Key parse(String externalId, boolean isCaseInsensitive) {
      int c = externalId.indexOf(':');
      if (c < 1 || c >= externalId.length() - 1) {
        return create(null, externalId, isCaseInsensitive);
      }
      return create(externalId.substring(0, c), externalId.substring(c + 1), isCaseInsensitive);
    }

    public abstract @Nullable String scheme();

    public abstract String id();

    public abstract boolean isCaseInsensitive();

    public boolean isScheme(String scheme) {
      return scheme.equals(scheme());
    }

    @Memoized
    public ObjectId sha1() {
      return sha1(isCaseInsensitive());
    }

    /**
     * Returns the SHA1 of the external ID that is used as note ID in the refs/meta/external-ids
     * notes branch.
     */
    @SuppressWarnings("deprecation") // Use Hashing.sha1 for compatibility.
    private ObjectId sha1(Boolean isCaseInsensitive) {
      String keyString = isCaseInsensitive ? get().toLowerCase(Locale.US) : get();
      return ObjectId.fromRaw(Hashing.sha1().hashString(keyString, UTF_8).asBytes());
    }

    @Memoized
    public ObjectId caseSensitiveSha1() {
      return sha1(false);
    }

    /**
     * Exports this external ID key as string with the format "scheme:id", or "id" if scheme is
     * null.
     *
     * <p>This string representation is used as subsection name in the Git config file that stores
     * the external ID.
     */
    public String get() {
      if (scheme() != null) {
        return scheme() + ":" + id();
      }
      return id();
    }

    @Override
    public final String toString() {
      return get();
    }

    @Override
    public final boolean equals(Object obj) {
      if (!(obj instanceof ExternalId.Key)) {
        return false;
      }
      ExternalId.Key o = (ExternalId.Key) obj;

      return sha1().equals(o.sha1());
    }

    @Override
    @Memoized
    public int hashCode() {
      return Objects.hash(sha1());
    }

    public static ImmutableSet<ExternalId.Key> from(Collection<ExternalId> extIds) {
      return extIds.stream().map(ExternalId::key).collect(toImmutableSet());
    }
  }

  @Deprecated
  public static ExternalId create(
      Key key,
      Account.Id accountId,
      @Nullable String email,
      @Nullable String hashedPassword,
      @Nullable ObjectId blobId) {
    return new AutoValue_ExternalId(
        key,
        accountId,
        key.isCaseInsensitive(),
        Strings.emptyToNull(email),
        Strings.emptyToNull(hashedPassword),
        blobId);
  }

  public static ExternalId create(
      Key key, Account.Id accountId, @Nullable String email, @Nullable ObjectId blobId) {
    return new AutoValue_ExternalId(
        key, accountId, key.isCaseInsensitive(), Strings.emptyToNull(email), null, blobId);
  }

  public abstract Key key();

  public abstract Account.Id accountId();

  public abstract boolean isCaseInsensitive();

  public abstract @Nullable String email();

  @Deprecated
  public abstract @Nullable String password();

  /**
   * ID of the note blob in the external IDs branch that stores this external ID. {@code null} if
   * the external ID was created in code and is not yet stored in Git.
   */
  public abstract @Nullable ObjectId blobId();

  public void checkThatBlobIdIsSet() {
    checkState(blobId() != null, "No blob ID set for external ID %s", key().get());
  }

  public boolean isScheme(String scheme) {
    return key().isScheme(scheme);
  }

  /**
   * For checking if two external IDs are equals the blobId is excluded and external IDs that have
   * different blob IDs but identical other fields are considered equal. This way an external ID
   * that was loaded from Git can be equal with an external ID that was created from code.
   */
  @Override
  public final boolean equals(Object obj) {
    if (!(obj instanceof ExternalId)) {
      return false;
    }
    ExternalId o = (ExternalId) obj;
    return Objects.equals(key(), o.key())
        && Objects.equals(accountId(), o.accountId())
        && isCaseInsensitive() == o.isCaseInsensitive()
        && Objects.equals(email(), o.email())
        && Objects.equals(password(), o.password());
  }

  @Memoized
  @Override
  public int hashCode() {
    return Objects.hash(key(), accountId(), isCaseInsensitive(), email(), password());
  }

  /**
   * Exports this external ID as Git config file text.
   *
   * <p>The Git config has exactly one externalId subsection with an accountId and optionally email
   * and password:
   *
   * <pre>
   * [externalId "username:jdoe"]
   *   accountId = 1003407
   *   email = jdoe@example.com
   *   password = bcrypt:4:LCbmSBDivK/hhGVQMfkDpA==:XcWn0pKYSVU/UJgOvhidkEtmqCp6oKB7
   * </pre>
   */
  @Override
  @Memoized
  public String toString() {
    Config c = new Config();
    writeToConfig(c);
    return c.toText();
  }

  public void writeToConfig(Config c) {
    String externalIdKey = key().get();
    // Do not use c.setInt(...) to write the account ID because c.setInt(...) persists integers
    // that can be expressed in KiB as a unit strings, e.g. "1024000" is stored as "100k". Using
    // c.setString(...) ensures that account IDs are human readable.
    c.setString(
        EXTERNAL_ID_SECTION, externalIdKey, ACCOUNT_ID_KEY, Integer.toString(accountId().get()));

    if (email() != null) {
      c.setString(EXTERNAL_ID_SECTION, externalIdKey, EMAIL_KEY, email());
    } else {
      c.unset(EXTERNAL_ID_SECTION, externalIdKey, EMAIL_KEY);
    }

    if (password() != null) {
      c.setString(EXTERNAL_ID_SECTION, externalIdKey, PASSWORD_KEY, password());
    } else {
      c.unset(EXTERNAL_ID_SECTION, externalIdKey, PASSWORD_KEY);
    }
  }
}
