// 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.entities;

import com.google.auto.value.AutoValue;
import com.google.gerrit.common.Nullable;
import java.sql.Timestamp;
import java.time.Instant;
import java.util.Objects;

/** Named group of one or more accounts, typically used for access controls. */
public final class AccountGroup {
  /**
   * Time when the audit subsystem was implemented, used as the default value for {@link #createdOn}
   * when one couldn't be determined from the audit log.
   */
  private static final Instant AUDIT_CREATION_INSTANT_MS = Instant.ofEpochMilli(1244489460000L);

  public static Timestamp auditCreationInstantTs() {
    return Timestamp.from(AUDIT_CREATION_INSTANT_MS);
  }

  public static NameKey nameKey(String n) {
    return new AutoValue_AccountGroup_NameKey(n);
  }

  /** Group name key */
  @AutoValue
  public abstract static class NameKey implements Comparable<NameKey> {
    abstract String name();

    public String get() {
      return name();
    }

    @Override
    public final int compareTo(NameKey o) {
      return name().compareTo(o.name());
    }

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

  public static UUID uuid(String n) {
    return new AutoValue_AccountGroup_UUID(n);
  }

  /** Globally unique identifier. */
  @AutoValue
  public abstract static class UUID implements Comparable<UUID> {
    abstract String uuid();

    public String get() {
      return uuid();
    }

    /** Parse an {@link AccountGroup.UUID} out of a string representation. */
    public static UUID parse(String str) {
      return AccountGroup.uuid(KeyUtil.decode(str));
    }

    /** Parse an {@link AccountGroup.UUID} out of a ref-name. */
    public static UUID fromRef(String ref) {
      if (ref == null) {
        return null;
      }
      if (ref.startsWith(RefNames.REFS_GROUPS)) {
        return fromRefPart(ref.substring(RefNames.REFS_GROUPS.length()));
      }
      return null;
    }

    /**
     * Parse an {@link AccountGroup.UUID} out of a part of a ref-name.
     *
     * @param refPart a ref name with the following syntax: {@code "12/1234..."}. We assume that the
     *     caller has trimmed any prefix.
     */
    public static UUID fromRefPart(String refPart) {
      String uuid = RefNames.parseShardedUuidFromRefPart(refPart);
      return uuid != null ? AccountGroup.uuid(uuid) : null;
    }

    @Override
    public final int compareTo(UUID o) {
      return uuid().compareTo(o.uuid());
    }

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

  /** @return true if the UUID is for a group managed within Gerrit. */
  public static boolean isInternalGroup(AccountGroup.UUID uuid) {
    return uuid.get().matches("^[0-9a-f]{40}$");
  }

  public static Id id(int id) {
    return new AutoValue_AccountGroup_Id(id);
  }

  /** Synthetic key to link to within the database */
  @AutoValue
  public abstract static class Id {
    abstract int id();

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

    /** Parse an AccountGroup.Id out of a string representation. */
    public static Id parse(String str) {
      return AccountGroup.id(Integer.parseInt(str));
    }

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

  /** Unique name of this group within the system. */
  protected NameKey name;

  /** Unique identity, to link entities as {@link #name} can change. */
  protected Id groupId;

  // DELETED: id = 3 (ownerGroupId)

  /** A textual description of the group's purpose. */
  @Nullable protected String description;

  // DELETED: id = 5 (groupType)
  // DELETED: id = 6 (externalName)

  protected boolean visibleToAll;

  // DELETED: id = 8 (emailOnlyAuthors)

  /** Globally unique identifier name for this group. */
  protected UUID groupUUID;

  /**
   * Identity of the group whose members can manage this group.
   *
   * <p>This can be a self-reference to indicate the group's members manage itself.
   */
  protected UUID ownerGroupUUID;

  @Nullable protected Timestamp createdOn;

  protected AccountGroup() {}

  public AccountGroup(
      AccountGroup.NameKey newName,
      AccountGroup.Id newId,
      AccountGroup.UUID uuid,
      Timestamp createdOn) {
    name = newName;
    groupId = newId;
    visibleToAll = false;
    groupUUID = uuid;
    ownerGroupUUID = groupUUID;
    this.createdOn = createdOn;
  }

  public AccountGroup(AccountGroup other) {
    name = other.name;
    groupId = other.groupId;
    description = other.description;
    visibleToAll = other.visibleToAll;
    groupUUID = other.groupUUID;
    ownerGroupUUID = other.ownerGroupUUID;
    createdOn = other.createdOn;
  }

  public AccountGroup.Id getId() {
    return groupId;
  }

  public String getName() {
    return name.get();
  }

  public AccountGroup.NameKey getNameKey() {
    return name;
  }

  public void setNameKey(AccountGroup.NameKey nameKey) {
    name = nameKey;
  }

  public String getDescription() {
    return description;
  }

  public void setDescription(String d) {
    description = d;
  }

  public AccountGroup.UUID getOwnerGroupUUID() {
    return ownerGroupUUID;
  }

  public void setOwnerGroupUUID(AccountGroup.UUID uuid) {
    ownerGroupUUID = uuid;
  }

  public void setVisibleToAll(boolean visibleToAll) {
    this.visibleToAll = visibleToAll;
  }

  public boolean isVisibleToAll() {
    return visibleToAll;
  }

  public AccountGroup.UUID getGroupUUID() {
    return groupUUID;
  }

  public void setGroupUUID(AccountGroup.UUID uuid) {
    groupUUID = uuid;
  }

  public Timestamp getCreatedOn() {
    return createdOn != null ? createdOn : auditCreationInstantTs();
  }

  public void setCreatedOn(Timestamp createdOn) {
    this.createdOn = createdOn;
  }

  @Override
  public boolean equals(Object o) {
    if (!(o instanceof AccountGroup)) {
      return false;
    }
    AccountGroup g = (AccountGroup) o;
    return Objects.equals(name, g.name)
        && Objects.equals(groupId, g.groupId)
        && Objects.equals(description, g.description)
        && visibleToAll == g.visibleToAll
        && Objects.equals(groupUUID, g.groupUUID)
        && Objects.equals(ownerGroupUUID, g.ownerGroupUUID)
        // Treat created on epoch identical regardless if underlying value is null.
        && getCreatedOn().equals(g.getCreatedOn());
  }

  @Override
  public int hashCode() {
    return Objects.hash(
        name, groupId, description, visibleToAll, groupUUID, ownerGroupUUID, createdOn);
  }

  @Override
  public String toString() {
    return getClass().getSimpleName()
        + "{"
        + "name="
        + name
        + ", groupId="
        + groupId
        + ", description="
        + description
        + ", visibleToAll="
        + visibleToAll
        + ", groupUUID="
        + groupUUID
        + ", ownerGroupUUID="
        + ownerGroupUUID
        + ", createdOn="
        + createdOn
        + "}";
  }
}
