// Copyright (C) 2008 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.reviewdb.client;

import static com.google.gerrit.reviewdb.client.RefNames.REFS_DRAFT_COMMENTS;
import static com.google.gerrit.reviewdb.client.RefNames.REFS_STARRED_CHANGES;
import static com.google.gerrit.reviewdb.client.RefNames.REFS_USERS;

import com.google.gerrit.extensions.client.DiffPreferencesInfo;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo;
import com.google.gwtorm.client.Column;
import com.google.gwtorm.client.IntKey;
import java.sql.Timestamp;

/**
 * Information about a single user.
 *
 * <p>A user may have multiple identities they can use to login to Gerrit (see ExternalId), but in
 * such cases they always map back to a single Account entity.
 *
 * <p>Entities "owned" by an Account (that is, their primary key contains the {@link Account.Id} key
 * as part of their key structure):
 *
 * <ul>
 *   <li>ExternalId: OpenID identities and email addresses known to be registered to this user.
 *       Multiple records can exist when the user has more than one public identity, such as a work
 *       and a personal email address.
 *   <li>{@link AccountGroupMember}: membership of the user in a specific human managed {@link
 *       AccountGroup}. Multiple records can exist when the user is a member of more than one group.
 *   <li>{@link AccountSshKey}: user's public SSH keys, for authentication through the internal SSH
 *       daemon. One record per SSH key uploaded by the user, keys are checked in random order until
 *       a match is found.
 *   <li>{@link DiffPreferencesInfo}: user's preferences for rendering side-to-side and unified diff
 * </ul>
 */
public final class Account {
  /** Key local to Gerrit to identify a user. */
  public static class Id extends IntKey<com.google.gwtorm.client.Key<?>> {
    private static final long serialVersionUID = 1L;

    @Column(id = 1)
    protected int id;

    protected Id() {}

    public Id(int id) {
      this.id = id;
    }

    @Override
    public int get() {
      return id;
    }

    @Override
    protected void set(int newValue) {
      id = newValue;
    }

    /** Parse an Account.Id out of a string representation. */
    public static Id parse(String str) {
      Id r = new Id();
      r.fromString(str);
      return r;
    }

    public static Id fromRef(String name) {
      if (name == null) {
        return null;
      }
      if (name.startsWith(REFS_USERS)) {
        return fromRefPart(name.substring(REFS_USERS.length()));
      } else if (name.startsWith(REFS_DRAFT_COMMENTS)) {
        return parseAfterShardedRefPart(name.substring(REFS_DRAFT_COMMENTS.length()));
      } else if (name.startsWith(REFS_STARRED_CHANGES)) {
        return parseAfterShardedRefPart(name.substring(REFS_STARRED_CHANGES.length()));
      }
      return null;
    }

    /**
     * Parse an Account.Id out of a part of a ref-name.
     *
     * @param name a ref name with the following syntax: {@code "34/1234..."}. We assume that the
     *     caller has trimmed any prefix.
     */
    public static Id fromRefPart(String name) {
      Integer id = RefNames.parseShardedRefPart(name);
      return id != null ? new Account.Id(id) : null;
    }

    public static Id parseAfterShardedRefPart(String name) {
      Integer id = RefNames.parseAfterShardedRefPart(name);
      return id != null ? new Account.Id(id) : null;
    }

    /**
     * Parse an Account.Id out of the last part of a ref name.
     *
     * <p>The input is a ref name of the form {@code ".../1234"}, where the suffix is a non-sharded
     * account ID. Ref names using a sharded ID should use {@link #fromRefPart(String)} instead for
     * greater safety.
     *
     * @param name ref name
     * @return account ID, or null if not numeric.
     */
    public static Id fromRefSuffix(String name) {
      Integer id = RefNames.parseRefSuffix(name);
      return id != null ? new Account.Id(id) : null;
    }
  }

  @Column(id = 1)
  protected Id accountId;

  /** Date and time the user registered with the review server. */
  @Column(id = 2)
  protected Timestamp registeredOn;

  /** Full name of the user ("Given-name Surname" style). */
  @Column(id = 3, notNull = false)
  protected String fullName;

  /** Email address the user prefers to be contacted through. */
  @Column(id = 4, notNull = false)
  protected String preferredEmail;

  // DELETED: id = 5 (contactFiledOn)

  // DELETED: id = 6 (generalPreferences)

  /**
   * Is this user inactive? This is used to avoid showing some users (eg. former employees) in
   * auto-suggest.
   */
  @Column(id = 7)
  protected boolean inactive;

  /** The user-settable status of this account (e.g. busy, OOO, available) */
  @Column(id = 8, notNull = false)
  protected String status;

  /** <i>computed</i> the username selected from the identities. */
  protected String userName;

  /** <i>stored in git, used for caching</i> the user's preferences. */
  private GeneralPreferencesInfo generalPreferences;

  /**
   * ID of the user branch from which the account was read, {@code null} if the account was read
   * from ReviewDb.
   */
  private String metaId;

  protected Account() {}

  /**
   * Create a new account.
   *
   * @param newId unique id, see {@link com.google.gerrit.server.Sequences#nextAccountId()}.
   * @param registeredOn when the account was registered.
   */
  public Account(Account.Id newId, Timestamp registeredOn) {
    this.accountId = newId;
    this.registeredOn = registeredOn;
  }

  /** Get local id of this account, to link with in other entities */
  public Account.Id getId() {
    return accountId;
  }

  /** Get the full name of the user ("Given-name Surname" style). */
  public String getFullName() {
    return fullName;
  }

  /** Set the full name of the user ("Given-name Surname" style). */
  public void setFullName(String name) {
    if (name != null && !name.trim().isEmpty()) {
      fullName = name.trim();
    } else {
      fullName = null;
    }
  }

  /** Email address the user prefers to be contacted through. */
  public String getPreferredEmail() {
    return preferredEmail;
  }

  /** Set the email address the user prefers to be contacted through. */
  public void setPreferredEmail(String addr) {
    preferredEmail = addr;
  }

  /**
   * Formats an account name.
   *
   * <p>If the account has a full name, it returns only the full name. Otherwise it returns a longer
   * form that includes the email address.
   */
  public String getName(String anonymousCowardName) {
    if (fullName != null) {
      return fullName;
    }
    if (preferredEmail != null) {
      return preferredEmail;
    }
    return getNameEmail(anonymousCowardName);
  }

  /**
   * Get the name and email address.
   *
   * <p>Example output:
   *
   * <ul>
   *   <li>{@code A U. Thor &lt;author@example.com&gt;}: full populated
   *   <li>{@code A U. Thor (12)}: missing email address
   *   <li>{@code Anonymous Coward &lt;author@example.com&gt;}: missing name
   *   <li>{@code Anonymous Coward (12)}: missing name and email address
   * </ul>
   */
  public String getNameEmail(String anonymousCowardName) {
    String name = fullName != null ? fullName : anonymousCowardName;
    StringBuilder b = new StringBuilder();
    b.append(name);
    if (preferredEmail != null) {
      b.append(" <");
      b.append(preferredEmail);
      b.append(">");
    } else if (accountId != null) {
      b.append(" (");
      b.append(accountId.get());
      b.append(")");
    }
    return b.toString();
  }

  /** Get the date and time the user first registered. */
  public Timestamp getRegisteredOn() {
    return registeredOn;
  }

  public GeneralPreferencesInfo getGeneralPreferencesInfo() {
    return generalPreferences;
  }

  public void setGeneralPreferences(GeneralPreferencesInfo p) {
    generalPreferences = p;
  }

  public String getMetaId() {
    return metaId;
  }

  public void setMetaId(String metaId) {
    this.metaId = metaId;
  }

  public boolean isActive() {
    return !inactive;
  }

  public void setActive(boolean active) {
    inactive = !active;
  }

  public String getStatus() {
    return status;
  }

  public void setStatus(String status) {
    this.status = status;
  }

  /** @return the computed user name for this account */
  public String getUserName() {
    return userName;
  }

  /** Update the computed user name property. */
  public void setUserName(String userName) {
    this.userName = userName;
  }

  @Override
  public boolean equals(Object o) {
    return o instanceof Account && ((Account) o).getId().equals(getId());
  }

  @Override
  public int hashCode() {
    return getId().get();
  }
}
