// 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.common.base.Preconditions.checkArgument;

import org.eclipse.jgit.util.NB;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class Fingerprint {
  private final byte[] fp;

  public static String toString(byte[] fp) {
    checkLength(fp);
    return String.format(
        "%04X %04X %04X %04X %04X  %04X %04X %04X %04X %04X",
        NB.decodeUInt16(fp, 0), NB.decodeUInt16(fp, 2), NB.decodeUInt16(fp, 4),
        NB.decodeUInt16(fp, 6), NB.decodeUInt16(fp, 8), NB.decodeUInt16(fp, 10),
        NB.decodeUInt16(fp, 12), NB.decodeUInt16(fp, 14),
        NB.decodeUInt16(fp, 16), NB.decodeUInt16(fp, 18));
  }

  public static long getId(byte[] fp) {
    return NB.decodeInt64(fp, 12);
  }

  public static Map<Long, Fingerprint> byId(Iterable<Fingerprint> fps) {
    Map<Long, Fingerprint> result = new HashMap<>();
    for (Fingerprint fp : fps) {
      result.put(fp.getId(), fp);
    }
    return Collections.unmodifiableMap(result);
  }

  private static byte[] checkLength(byte[] fp) {
    checkArgument(fp.length == 20,
        "fingerprint must be 20 bytes, got %s", fp.length);
    return fp;
  }

  /**
   * Wrap a fingerprint byte array.
   * <p>
   * The newly created Fingerprint object takes ownership of the byte array,
   * which must not be subsequently modified. (Most callers, such as hex
   * decoders and {@code
   * org.bouncycastle.openpgp.PGPPublicKey#getFingerprint()}, already produce
   * fresh byte arrays).
   *
   * @param fp 20-byte fingerprint byte array to wrap.
   */
  public Fingerprint(byte[] fp) {
    this.fp = checkLength(fp);
  }

  /**
   * Wrap a portion of a fingerprint byte array.
   * <p>
   * Unlike {@link #Fingerprint(byte[])}, creates a new copy of the byte array.
   *
   * @param buf byte array to wrap; must have at least {@code off + 20} bytes.
   * @param off offset in buf.
   */
  public Fingerprint(byte[] buf, int off) {
    int expected = 20 + off;
    checkArgument(buf.length >= expected,
        "fingerprint buffer must have at least %s bytes, got %s",
        expected, buf.length);
    this.fp = new byte[20];
    System.arraycopy(buf, off, fp, 0, 20);
  }

  public byte[] get() {
    return fp;
  }

  public boolean equalsBytes(byte[] bytes) {
    return Arrays.equals(fp, bytes);
  }

  @Override
  public int hashCode() {
    // Same hash code as ObjectId: second int word.
    return NB.decodeInt32(fp, 4);
  }

  @Override
  public boolean equals(Object o) {
    return (o instanceof Fingerprint) && equalsBytes(((Fingerprint) o).fp);
  }

  @Override
  public String toString() {
    return toString(fp);
  }

  public long getId() {
    return getId(fp);
  }
}
