// Copyright (C) 2015 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.gpg;

import static com.google.gerrit.gpg.PublicKeyStore.REFS_GPG_KEYS;
import static com.google.gerrit.gpg.PublicKeyStore.keyIdToString;
import static com.google.gerrit.gpg.PublicKeyStore.keyObjectId;
import static com.google.gerrit.gpg.PublicKeyStore.keyToString;
import static com.google.gerrit.gpg.testutil.TestKeys.validKeyWithExpiration;
import static com.google.gerrit.gpg.testutil.TestKeys.validKeyWithSecondUserId;
import static com.google.gerrit.gpg.testutil.TestKeys.validKeyWithoutExpiration;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import com.google.common.collect.Iterators;
import com.google.gerrit.gpg.testutil.TestKey;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.notes.NoteMap;
import org.eclipse.jgit.revwalk.RevWalk;
import org.junit.Before;
import org.junit.Test;

public class PublicKeyStoreTest {
  private TestRepository<?> tr;
  private PublicKeyStore store;

  @Before
  public void setUp() throws Exception {
    tr = new TestRepository<>(new InMemoryRepository(new DfsRepositoryDescription("pubkeys")));
    store = new PublicKeyStore(tr.getRepository());
  }

  @Test
  public void testKeyIdToString() throws Exception {
    PGPPublicKey key = validKeyWithoutExpiration().getPublicKey();
    assertEquals("46328A8C", keyIdToString(key.getKeyID()));
  }

  @Test
  public void testKeyToString() throws Exception {
    PGPPublicKey key = validKeyWithoutExpiration().getPublicKey();
    assertEquals(
        "46328A8C Testuser One <test1@example.com>"
            + " (04AE A7ED 2F82 1133 E5B1  28D1 ED06 25DC 4632 8A8C)",
        keyToString(key));
  }

  @Test
  public void testKeyObjectId() throws Exception {
    PGPPublicKey key = validKeyWithoutExpiration().getPublicKey();
    String objId = keyObjectId(key.getKeyID()).name();
    assertEquals("ed0625dc46328a8c000000000000000000000000", objId);
    assertEquals(keyIdToString(key.getKeyID()).toLowerCase(), objId.substring(8, 16));
  }

  @Test
  public void get() throws Exception {
    TestKey key1 = validKeyWithoutExpiration();
    tr.branch(REFS_GPG_KEYS)
        .commit()
        .add(keyObjectId(key1.getKeyId()).name(), key1.getPublicKeyArmored())
        .create();
    TestKey key2 = validKeyWithExpiration();
    tr.branch(REFS_GPG_KEYS)
        .commit()
        .add(keyObjectId(key2.getKeyId()).name(), key2.getPublicKeyArmored())
        .create();

    assertKeys(key1.getKeyId(), key1);
    assertKeys(key2.getKeyId(), key2);
  }

  @Test
  public void getMultiple() throws Exception {
    TestKey key1 = validKeyWithoutExpiration();
    TestKey key2 = validKeyWithExpiration();
    tr.branch(REFS_GPG_KEYS)
        .commit()
        .add(
            keyObjectId(key1.getKeyId()).name(),
            key1.getPublicKeyArmored()
                // Mismatched for this key ID, but we can still read it out.
                + key2.getPublicKeyArmored())
        .create();
    assertKeys(key1.getKeyId(), key1, key2);
  }

  @Test
  public void save() throws Exception {
    TestKey key1 = validKeyWithoutExpiration();
    TestKey key2 = validKeyWithExpiration();
    store.add(key1.getPublicKeyRing());
    store.add(key2.getPublicKeyRing());

    assertEquals(RefUpdate.Result.NEW, store.save(newCommitBuilder()));

    assertKeys(key1.getKeyId(), key1);
    assertKeys(key2.getKeyId(), key2);
  }

  @Test
  public void saveAppendsToExistingList() throws Exception {
    TestKey key1 = validKeyWithoutExpiration();
    TestKey key2 = validKeyWithExpiration();
    tr.branch(REFS_GPG_KEYS)
        .commit()
        // Mismatched for this key ID, but we can still read it out.
        .add(keyObjectId(key1.getKeyId()).name(), key2.getPublicKeyArmored())
        .create();

    store.add(key1.getPublicKeyRing());
    assertEquals(RefUpdate.Result.FAST_FORWARD, store.save(newCommitBuilder()));

    assertKeys(key1.getKeyId(), key1, key2);

    try (ObjectReader reader = tr.getRepository().newObjectReader();
        RevWalk rw = new RevWalk(reader)) {
      NoteMap notes =
          NoteMap.read(
              reader,
              tr.getRevWalk()
                  .parseCommit(tr.getRepository().exactRef(REFS_GPG_KEYS).getObjectId()));
      String contents =
          new String(reader.open(notes.get(keyObjectId(key1.getKeyId()))).getBytes(), UTF_8);
      String header = "-----BEGIN PGP PUBLIC KEY BLOCK-----";
      int i1 = contents.indexOf(header);
      assertTrue(i1 >= 0);
      int i2 = contents.indexOf(header, i1 + header.length());
      assertTrue(i2 >= 0);
    }
  }

  @Test
  public void updateExisting() throws Exception {
    TestKey key5 = validKeyWithSecondUserId();
    PGPPublicKeyRing keyRing = key5.getPublicKeyRing();
    PGPPublicKey key = keyRing.getPublicKey();
    PGPPublicKey subKey =
        keyRing.getPublicKey(Iterators.get(keyRing.getPublicKeys(), 1).getKeyID());
    store.add(keyRing);
    assertEquals(RefUpdate.Result.NEW, store.save(newCommitBuilder()));

    assertUserIds(
        store.get(key5.getKeyId()).iterator().next(),
        "Testuser Five <test5@example.com>",
        "foo:myId");

    keyRing = PGPPublicKeyRing.removePublicKey(keyRing, subKey);
    keyRing = PGPPublicKeyRing.removePublicKey(keyRing, key);
    key = PGPPublicKey.removeCertification(key, "foo:myId");
    keyRing = PGPPublicKeyRing.insertPublicKey(keyRing, key);
    keyRing = PGPPublicKeyRing.insertPublicKey(keyRing, subKey);
    store.add(keyRing);
    assertEquals(RefUpdate.Result.FAST_FORWARD, store.save(newCommitBuilder()));

    Iterator<PGPPublicKeyRing> keyRings = store.get(key.getKeyID()).iterator();
    keyRing = keyRings.next();
    assertFalse(keyRings.hasNext());
    assertUserIds(keyRing, "Testuser Five <test5@example.com>");
  }

  @Test
  public void remove() throws Exception {
    TestKey key1 = validKeyWithoutExpiration();
    store.add(key1.getPublicKeyRing());
    assertEquals(RefUpdate.Result.NEW, store.save(newCommitBuilder()));
    assertKeys(key1.getKeyId(), key1);

    store.remove(key1.getPublicKey().getFingerprint());
    assertEquals(RefUpdate.Result.FAST_FORWARD, store.save(newCommitBuilder()));
    assertKeys(key1.getKeyId());
  }

  @Test
  public void removeNonexisting() throws Exception {
    TestKey key1 = validKeyWithoutExpiration();
    store.add(key1.getPublicKeyRing());
    assertEquals(RefUpdate.Result.NEW, store.save(newCommitBuilder()));

    TestKey key2 = validKeyWithExpiration();
    store.remove(key2.getPublicKey().getFingerprint());
    assertEquals(RefUpdate.Result.NO_CHANGE, store.save(newCommitBuilder()));
    assertKeys(key1.getKeyId(), key1);
  }

  @Test
  public void addThenRemove() throws Exception {
    TestKey key1 = validKeyWithoutExpiration();
    store.add(key1.getPublicKeyRing());
    store.remove(key1.getPublicKey().getFingerprint());
    assertEquals(RefUpdate.Result.NO_CHANGE, store.save(newCommitBuilder()));
    assertKeys(key1.getKeyId());
  }

  private void assertKeys(long keyId, TestKey... expected) throws Exception {
    Set<String> expectedStrings = new TreeSet<>();
    for (TestKey k : expected) {
      expectedStrings.add(keyToString(k.getPublicKey()));
    }
    PGPPublicKeyRingCollection actual = store.get(keyId);
    Set<String> actualStrings = new TreeSet<>();
    for (PGPPublicKeyRing k : actual) {
      actualStrings.add(keyToString(k.getPublicKey()));
    }
    assertEquals(expectedStrings, actualStrings);
  }

  private void assertUserIds(PGPPublicKeyRing keyRing, String... expected) throws Exception {
    List<String> actual = new ArrayList<>();
    Iterator<String> userIds =
        store.get(keyRing.getPublicKey().getKeyID()).iterator().next().getPublicKey().getUserIDs();
    while (userIds.hasNext()) {
      actual.add(userIds.next());
    }

    assertEquals(Arrays.asList(expected), actual);
  }

  private CommitBuilder newCommitBuilder() {
    CommitBuilder cb = new CommitBuilder();
    PersonIdent ident = new PersonIdent("A U Thor", "author@example.com");
    cb.setAuthor(ident);
    cb.setCommitter(ident);
    return cb;
  }
}
