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

import static com.google.common.base.Preconditions.checkState;
import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.toList;

import com.google.common.base.Strings;
import com.google.common.collect.Ordering;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.exceptions.InvalidSshKeyException;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.meta.MetaDataUpdate;
import com.google.gerrit.server.git.meta.VersionedMetaData;
import com.google.gerrit.server.ssh.SshKeyCreator;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.google.inject.assistedinject.Assisted;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.Repository;

/**
 * 'authorized_keys' file in the refs/users/CD/ABCD branches of the All-Users repository.
 *
 * <p>The `authorized_keys' files stores the public SSH keys of the user. The file format matches
 * the standard SSH file format, which means that each key is stored on a separate line (see
 * https://en.wikibooks.org/wiki/OpenSSH/Client_Configuration_Files#.7E.2F.ssh.2Fauthorized_keys).
 *
 * <p>The order of the keys in the file determines the sequence numbers of the keys. The first line
 * corresponds to sequence number 1.
 *
 * <p>Invalid keys are marked with the prefix <code># INVALID</code>.
 *
 * <p>To keep the sequence numbers intact when a key is deleted, a <code># DELETED</code> line is
 * inserted at the position where the key was deleted.
 *
 * <p>Other comment lines are ignored on read, and are not written back when the file is modified.
 */
public class VersionedAuthorizedKeys extends VersionedMetaData {

  /** Read/write SSH keys by user ID. */
  @Singleton
  public static class Accessor {
    private final GitRepositoryManager repoManager;
    private final AllUsersName allUsersName;
    private final VersionedAuthorizedKeys.Factory authorizedKeysFactory;
    private final Provider<MetaDataUpdate.User> metaDataUpdateFactory;
    private final IdentifiedUser.GenericFactory userFactory;

    @Inject
    Accessor(
        GitRepositoryManager repoManager,
        AllUsersName allUsersName,
        VersionedAuthorizedKeys.Factory authorizedKeysFactory,
        Provider<MetaDataUpdate.User> metaDataUpdateFactory,
        IdentifiedUser.GenericFactory userFactory) {
      this.repoManager = repoManager;
      this.allUsersName = allUsersName;
      this.authorizedKeysFactory = authorizedKeysFactory;
      this.metaDataUpdateFactory = metaDataUpdateFactory;
      this.userFactory = userFactory;
    }

    public List<AccountSshKey> getKeys(Account.Id accountId)
        throws IOException, ConfigInvalidException {
      return read(accountId).getKeys();
    }

    public AccountSshKey getKey(Account.Id accountId, int seq)
        throws IOException, ConfigInvalidException {
      return read(accountId).getKey(seq);
    }

    @CanIgnoreReturnValue
    public synchronized AccountSshKey addKey(Account.Id accountId, String pub)
        throws IOException, ConfigInvalidException, InvalidSshKeyException {
      VersionedAuthorizedKeys authorizedKeys = read(accountId);
      AccountSshKey key = authorizedKeys.addKey(pub);
      commit(authorizedKeys);
      return key;
    }

    public synchronized void deleteKey(Account.Id accountId, int seq)
        throws IOException, ConfigInvalidException {
      VersionedAuthorizedKeys authorizedKeys = read(accountId);
      if (authorizedKeys.deleteKey(seq)) {
        commit(authorizedKeys);
      }
    }

    public synchronized void markKeyInvalid(Account.Id accountId, int seq)
        throws IOException, ConfigInvalidException {
      VersionedAuthorizedKeys authorizedKeys = read(accountId);
      if (authorizedKeys.markKeyInvalid(seq)) {
        commit(authorizedKeys);
      }
    }

    private VersionedAuthorizedKeys read(Account.Id accountId)
        throws IOException, ConfigInvalidException {
      try (Repository git = repoManager.openRepository(allUsersName)) {
        VersionedAuthorizedKeys authorizedKeys = authorizedKeysFactory.create(accountId);
        authorizedKeys.load(allUsersName, git);
        return authorizedKeys;
      }
    }

    private void commit(VersionedAuthorizedKeys authorizedKeys) throws IOException {
      try (MetaDataUpdate md =
          metaDataUpdateFactory
              .get()
              .create(allUsersName, userFactory.create(authorizedKeys.accountId))) {
        authorizedKeys.commit(md);
      }
    }
  }

  public static class SimpleSshKeyCreator implements SshKeyCreator {
    @Override
    public AccountSshKey create(Account.Id accountId, int seq, String encoded) {
      return AccountSshKey.create(accountId, seq, encoded);
    }
  }

  public interface Factory {
    VersionedAuthorizedKeys create(Account.Id accountId);
  }

  private final SshKeyCreator sshKeyCreator;
  private final Account.Id accountId;
  private final String ref;
  private List<Optional<AccountSshKey>> keys;

  @Inject
  public VersionedAuthorizedKeys(SshKeyCreator sshKeyCreator, @Assisted Account.Id accountId) {
    this.sshKeyCreator = sshKeyCreator;
    this.accountId = accountId;
    this.ref = RefNames.refsUsers(accountId);
  }

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

  @Override
  protected void onLoad() throws IOException {
    keys = AuthorizedKeys.parse(accountId, readUTF8(AuthorizedKeys.FILE_NAME));
  }

  @Override
  protected boolean onSave(CommitBuilder commit) throws IOException {
    if (Strings.isNullOrEmpty(commit.getMessage())) {
      commit.setMessage("Updated SSH keys\n");
    }

    saveUTF8(AuthorizedKeys.FILE_NAME, AuthorizedKeys.serialize(keys));
    return true;
  }

  /** Returns all SSH keys. */
  private List<AccountSshKey> getKeys() {
    checkLoaded();
    return keys.stream().filter(Optional::isPresent).map(Optional::get).collect(toList());
  }

  /**
   * Returns the SSH key with the given sequence number.
   *
   * @param seq sequence number
   * @return the SSH key, <code>null</code> if there is no SSH key with this sequence number, or if
   *     the SSH key with this sequence number has been deleted
   */
  @Nullable
  private AccountSshKey getKey(int seq) {
    checkLoaded();
    return keys.get(seq - 1).orElse(null);
  }

  /**
   * Adds a new public SSH key.
   *
   * <p>If the specified public key exists already, the existing key is returned.
   *
   * @param pub the public SSH key to be added
   * @return the new SSH key
   */
  private AccountSshKey addKey(String pub) throws InvalidSshKeyException {
    checkLoaded();

    for (Optional<AccountSshKey> key : keys) {
      if (key.isPresent() && key.get().sshPublicKey().trim().equals(pub.trim())) {
        return key.get();
      }
    }

    int seq = keys.size() + 1;
    AccountSshKey key = sshKeyCreator.create(accountId, seq, pub);
    keys.add(Optional.of(key));
    return key;
  }

  /**
   * Deletes the SSH key with the given sequence number.
   *
   * @param seq the sequence number
   * @return <code>true</code> if a key with this sequence number was found and deleted, <code>false
   *     </code> if no key with the given sequence number exists
   */
  private boolean deleteKey(int seq) {
    checkLoaded();
    if (seq <= keys.size() && keys.get(seq - 1).isPresent()) {
      keys.set(seq - 1, Optional.empty());
      return true;
    }
    return false;
  }

  /**
   * Marks the SSH key with the given sequence number as invalid.
   *
   * @param seq the sequence number
   * @return <code>true</code> if a key with this sequence number was found and marked as invalid,
   *     <code>false</code> if no key with the given sequence number exists or if the key was
   *     already marked as invalid
   */
  private boolean markKeyInvalid(int seq) {
    checkLoaded();

    Optional<AccountSshKey> key = keys.get(seq - 1);
    if (key.isPresent() && key.get().valid()) {
      keys.set(seq - 1, Optional.of(AccountSshKey.createInvalid(key.get())));
      return true;
    }
    return false;
  }

  /**
   * Sets new SSH keys.
   *
   * <p>The existing SSH keys are overwritten.
   *
   * @param newKeys the new public SSH keys
   */
  public void setKeys(Collection<AccountSshKey> newKeys) {
    Ordering<AccountSshKey> o = Ordering.from(comparing(AccountSshKey::seq));
    keys = new ArrayList<>(Collections.nCopies(o.max(newKeys).seq(), Optional.empty()));
    for (AccountSshKey key : newKeys) {
      keys.set(key.seq() - 1, Optional.of(key));
    }
  }

  private void checkLoaded() {
    checkState(keys != null, "SSH keys not loaded yet");
  }
}
