// 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 com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
import com.google.gerrit.common.errors.InvalidSshKeyException;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountSshKey;
import com.google.gerrit.reviewdb.client.AccountSshKey.Id;
import com.google.gerrit.reviewdb.client.RefNames;
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.MetaDataUpdate;
import com.google.gerrit.server.git.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 org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.Repository;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

/**
 * 'authorized_keys' file in the refs/users/CD/ABCD branches of the All-Users
 * repository.
 *
 * 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).
 *
 * The order of the keys in the file determines the sequence numbers of the
 * keys. The first line corresponds to sequence number 1.
 *
 * Invalid keys are marked with the prefix <code># INVALID</code>.
 *
 * 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.
 *
 * Other comment lines are ignored on read, and are not written back when the
 * file is modified.
 */
public class VersionedAuthorizedKeys extends VersionedMetaData {
  @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);
    }

    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(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(Id id, String encoded) {
      return new AccountSshKey(id, 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 Lists.newArrayList(Optional.presentInstances(keys));
  }

  /**
   * 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
   */
  private AccountSshKey getKey(int seq) {
    checkLoaded();
    Optional<AccountSshKey> key = keys.get(seq - 1);
    return key.orNull();
  }

  /**
   * Adds a new public SSH key.
   *
   * 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
   * @throws InvalidSshKeyException
   */
  private AccountSshKey addKey(String pub) throws InvalidSshKeyException {
    checkLoaded();

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

    int seq = keys.size() + 1;
    AccountSshKey.Id keyId = new AccountSshKey.Id(accountId, seq);
    AccountSshKey key = sshKeyCreator.create(keyId, 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.<AccountSshKey> absent());
      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();
    AccountSshKey key = getKey(seq);
    if (key != null && key.isValid()) {
      key.setInvalid();
      return true;
    }
    return false;
  }

  /**
   * Sets new SSH keys.
   *
   * The existing SSH keys are overwritten.
   *
   * @param newKeys the new public SSH keys
   */
  public void setKeys(Collection<AccountSshKey> newKeys) {
    Ordering<AccountSshKey> o =
        Ordering.natural().onResultOf(new Function<AccountSshKey, Integer>() {
          @Override
          public Integer apply(AccountSshKey sshKey) {
            return sshKey.getKey().get();
          }
        });
    keys = new ArrayList<>(Collections.nCopies(o.max(newKeys).getKey().get(),
        Optional.<AccountSshKey> absent()));
    for (AccountSshKey key : newKeys) {
      keys.set(key.getKey().get() - 1, Optional.of(key));
    }
  }

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