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

import static com.google.common.base.Preconditions.checkState;
import static java.util.Objects.requireNonNull;

import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.exceptions.DuplicateKeyException;
import com.google.gerrit.server.account.ProjectWatches.NotifyType;
import com.google.gerrit.server.account.ProjectWatches.ProjectWatchKey;
import com.google.gerrit.server.account.externalids.ExternalIds;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.config.CachedPreferences;
import com.google.gerrit.server.git.ValidationError;
import com.google.gerrit.server.git.meta.MetaDataUpdate;
import com.google.gerrit.server.git.meta.VersionedMetaData;
import com.google.gerrit.server.util.time.TimeUtil;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevSort;

/**
 * Reads/writes account data from/to a user branch in the {@code All-Users} repository.
 *
 * <p>This is the low-level API for account creation and account updates. Most callers should use
 * {@link AccountsUpdate} for creating and updating accounts.
 *
 * <p>This class can read/write account properties, preferences (general, diff and edit preferences)
 * and project watches.
 *
 * <p>The following files are read/written:
 *
 * <ul>
 *   <li>'account.config': Contains the account properties. Parsing and writing it is delegated to
 *       {@link AccountProperties}.
 *   <li>'preferences.config': Contains the preferences. Parsing and writing it is delegated to
 *       {@link StoredPreferences}.
 *   <li>'account.config': Contains the project watches. Parsing and writing it is delegated to
 *       {@link ProjectWatches}.
 * </ul>
 *
 * <p>The commit date of the first commit on the user branch is used as registration date of the
 * account. The first commit may be an empty commit (since all config files are optional).
 */
public class AccountConfig extends VersionedMetaData implements ValidationError.Sink {
  private final Account.Id accountId;
  private final AllUsersName allUsersName;
  private final Repository repo;
  private final String ref;

  private Optional<AccountProperties> loadedAccountProperties;
  private Optional<ObjectId> externalIdsRev;
  private ProjectWatches projectWatches;
  private StoredPreferences preferences;
  private Optional<InternalAccountUpdate> accountUpdate = Optional.empty();
  private List<ValidationError> validationErrors;

  public AccountConfig(Account.Id accountId, AllUsersName allUsersName, Repository allUsersRepo) {
    this.accountId = requireNonNull(accountId, "accountId");
    this.allUsersName = requireNonNull(allUsersName, "allUsersName");
    this.repo = requireNonNull(allUsersRepo, "allUsersRepo");
    this.ref = RefNames.refsUsers(accountId);
  }

  @Override
  protected String getRefName() {
    return ref;
  }

  public AccountConfig load() throws IOException, ConfigInvalidException {
    load(allUsersName, repo);
    return this;
  }

  public AccountConfig load(ObjectId rev) throws IOException, ConfigInvalidException {
    load(allUsersName, repo, rev);
    return this;
  }

  /**
   * Get the loaded account.
   *
   * @return the loaded account, {@link Optional#empty()} if load didn't find the account because it
   *     doesn't exist
   * @throws IllegalStateException if the account was not loaded yet
   */
  public Optional<Account> getLoadedAccount() {
    checkLoaded();
    return loadedAccountProperties.map(AccountProperties::getAccount);
  }

  /**
   * Returns the revision of the {@code refs/meta/external-ids} branch.
   *
   * <p>This revision can be used to load the external IDs of the loaded account lazily via {@link
   * ExternalIds#byAccount(com.google.gerrit.entities.Account.Id, ObjectId)}.
   *
   * @return revision of the {@code refs/meta/external-ids} branch, {@link Optional#empty()} if no
   *     {@code refs/meta/external-ids} branch exists
   */
  public Optional<ObjectId> getExternalIdsRev() {
    checkLoaded();
    return externalIdsRev;
  }

  /**
   * Get the project watches of the loaded account.
   *
   * @return the project watches of the loaded account
   */
  public ImmutableMap<ProjectWatchKey, ImmutableSet<NotifyType>> getProjectWatches() {
    checkLoaded();
    return projectWatches.getProjectWatches();
  }

  /**
   * Sets the account. This means the loaded account will be overwritten with the given account.
   *
   * <p>Changing the registration date of an account is not supported.
   *
   * @param account account that should be set
   * @throws IllegalStateException if the account was not loaded yet
   */
  public AccountConfig setAccount(Account account) {
    checkLoaded();
    this.loadedAccountProperties =
        Optional.of(
            new AccountProperties(account.id(), account.registeredOn(), new Config(), null));
    this.accountUpdate =
        Optional.of(
            InternalAccountUpdate.builder()
                .setActive(account.isActive())
                .setFullName(account.fullName())
                .setDisplayName(account.displayName())
                .setPreferredEmail(account.preferredEmail())
                .setStatus(account.status())
                .build());
    return this;
  }

  /**
   * Creates a new account.
   *
   * @return the new account
   * @throws DuplicateKeyException if the user branch already exists
   */
  public Account getNewAccount() throws DuplicateKeyException {
    return getNewAccount(TimeUtil.nowTs());
  }

  /**
   * Creates a new account.
   *
   * @return the new account
   * @throws DuplicateKeyException if the user branch already exists
   */
  Account getNewAccount(Timestamp registeredOn) throws DuplicateKeyException {
    checkLoaded();
    if (revision != null) {
      throw new DuplicateKeyException(String.format("account %s already exists", accountId));
    }
    this.loadedAccountProperties =
        Optional.of(new AccountProperties(accountId, registeredOn, new Config(), null));
    return loadedAccountProperties.map(AccountProperties::getAccount).get();
  }

  public AccountConfig setAccountUpdate(InternalAccountUpdate accountUpdate) {
    this.accountUpdate = Optional.of(accountUpdate);
    return this;
  }

  /**
   * Returns the content of the {@code preferences.config} file wrapped as {@link
   * CachedPreferences}.
   */
  CachedPreferences asCachedPreferences() {
    checkLoaded();
    return CachedPreferences.fromConfig(preferences.getRaw());
  }

  @Override
  protected void onLoad() throws IOException, ConfigInvalidException {
    if (revision != null) {
      rw.reset();
      rw.markStart(revision);
      rw.sort(RevSort.REVERSE);
      Timestamp registeredOn = new Timestamp(rw.next().getCommitTime() * 1000L);

      Config accountConfig = readConfig(AccountProperties.ACCOUNT_CONFIG);
      loadedAccountProperties =
          Optional.of(new AccountProperties(accountId, registeredOn, accountConfig, revision));

      projectWatches = new ProjectWatches(accountId, readConfig(ProjectWatches.WATCH_CONFIG), this);

      preferences =
          new StoredPreferences(
              accountId,
              readConfig(StoredPreferences.PREFERENCES_CONFIG),
              StoredPreferences.readDefaultConfig(allUsersName, repo),
              this);

      projectWatches.parse();
      preferences.parse();
    } else {
      loadedAccountProperties = Optional.empty();

      projectWatches = new ProjectWatches(accountId, new Config(), this);

      preferences =
          new StoredPreferences(
              accountId,
              new Config(),
              StoredPreferences.readDefaultConfig(allUsersName, repo),
              this);
    }

    Ref externalIdsRef = repo.exactRef(RefNames.REFS_EXTERNAL_IDS);
    externalIdsRev = Optional.ofNullable(externalIdsRef).map(Ref::getObjectId);
  }

  @Override
  public RevCommit commit(MetaDataUpdate update) throws IOException {
    RevCommit c = super.commit(update);
    loadedAccountProperties.get().setMetaId(c);
    return c;
  }

  @Override
  protected boolean onSave(CommitBuilder commit) throws IOException, ConfigInvalidException {
    checkLoaded();

    if (!loadedAccountProperties.isPresent()) {
      return false;
    }

    if (revision != null) {
      if (Strings.isNullOrEmpty(commit.getMessage())) {
        commit.setMessage("Update account\n");
      }
    } else {
      if (Strings.isNullOrEmpty(commit.getMessage())) {
        commit.setMessage("Create account\n");
      }

      Timestamp registeredOn = loadedAccountProperties.get().getRegisteredOn();
      commit.setAuthor(new PersonIdent(commit.getAuthor(), registeredOn));
      commit.setCommitter(new PersonIdent(commit.getCommitter(), registeredOn));
    }

    saveAccount();
    saveProjectWatches();
    savePreferences();

    accountUpdate = Optional.empty();

    return true;
  }

  private void saveAccount() throws IOException {
    if (accountUpdate.isPresent()) {
      saveConfig(
          AccountProperties.ACCOUNT_CONFIG,
          loadedAccountProperties.get().save(accountUpdate.get()));
    }
  }

  private void saveProjectWatches() throws IOException {
    if (accountUpdate.isPresent()
        && (!accountUpdate.get().getDeletedProjectWatches().isEmpty()
            || !accountUpdate.get().getUpdatedProjectWatches().isEmpty())) {
      Map<ProjectWatchKey, Set<NotifyType>> newProjectWatches =
          new HashMap<>(projectWatches.getProjectWatches());
      accountUpdate.get().getDeletedProjectWatches().forEach(newProjectWatches::remove);
      accountUpdate.get().getUpdatedProjectWatches().forEach(newProjectWatches::put);
      saveConfig(ProjectWatches.WATCH_CONFIG, projectWatches.save(newProjectWatches));
    }
  }

  private void savePreferences() throws IOException, ConfigInvalidException {
    if (!accountUpdate.isPresent()
        || (!accountUpdate.get().getGeneralPreferences().isPresent()
            && !accountUpdate.get().getDiffPreferences().isPresent()
            && !accountUpdate.get().getEditPreferences().isPresent())) {
      return;
    }

    saveConfig(
        StoredPreferences.PREFERENCES_CONFIG,
        preferences.saveGeneralPreferences(
            accountUpdate.get().getGeneralPreferences(),
            accountUpdate.get().getDiffPreferences(),
            accountUpdate.get().getEditPreferences()));
  }

  private void checkLoaded() {
    checkState(loadedAccountProperties != null, "Account %s not loaded yet", accountId.get());
  }

  /**
   * Get the validation errors, if any were discovered during parsing the account data.
   *
   * @return list of errors; empty list if there are no errors.
   */
  public List<ValidationError> getValidationErrors() {
    if (validationErrors != null) {
      return ImmutableList.copyOf(validationErrors);
    }
    return ImmutableList.of();
  }

  @Override
  public void error(ValidationError error) {
    if (validationErrors == null) {
      validationErrors = new ArrayList<>(4);
    }
    validationErrors.add(error);
  }
}
