// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0

package org.pgpainless.key

import java.net.URI
import java.nio.Buffer
import java.nio.ByteBuffer
import java.nio.charset.Charset
import org.bouncycastle.openpgp.PGPKeyRing
import org.bouncycastle.openpgp.PGPPublicKey
import org.bouncycastle.openpgp.PGPSecretKey
import org.bouncycastle.util.encoders.Hex

class OpenPgpV4Fingerprint : OpenPgpFingerprint {

    constructor(fingerprint: String) : super(fingerprint)

    constructor(bytes: ByteArray) : super(bytes)

    constructor(key: PGPPublicKey) : super(key)

    constructor(key: PGPSecretKey) : super(key)

    constructor(keys: PGPKeyRing) : super(keys)

    override fun getVersion() = 4

    override val keyId: Long
        get() {
            val bytes = Hex.decode(toString().toByteArray(Charset.forName("UTF-8")))
            val buf = ByteBuffer.wrap(bytes)

            // The key id is the right-most 8 bytes (conveniently a long)
            // We have to cast here in order to be compatible with java 8
            // https://github.com/eclipse/jetty.project/issues/3244
            (buf as Buffer).position(12) // 20 - 8 bytes = offset 12
            return buf.getLong()
        }

    override fun isValid(fingerprint: String): Boolean {
        return fingerprint.matches("^[0-9A-F]{40}$".toRegex())
    }

    fun toUri(): URI = URI(SCHEME, toString(), null)

    override fun prettyPrint(): String {
        return buildString {
            for (i in 0..4) {
                append(fingerprint, i * 4, (i + 1) * 4).append(' ')
            }
            append(' ')
            for (i in 5..8) {
                append(fingerprint, i * 4, (i + 1) * 4).append(' ')
            }
            append(fingerprint, 36, 40)
        }
    }

    companion object {
        @JvmStatic val SCHEME = "openpgp4fpr"

        @JvmStatic
        fun fromUri(uri: URI): OpenPgpV4Fingerprint {
            if (SCHEME != uri.scheme) {
                throw IllegalArgumentException("URI scheme MUST equal '$SCHEME'.")
            }
            return OpenPgpV4Fingerprint(uri.schemeSpecificPart)
        }
    }
}
