/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
 * This source file is part of the Cangjie project, licensed under Apache-2.0
 * with Runtime Library Exception.
 *
 * See https://cangjie-lang.cn/pages/LICENSE for license information.
 */

package stdx.crypto.common

/**
 * Represents a single entry of PEM file format.
 * Could be a certificate, a key, certificate request or one of other kinds specified as per RFC7468
 * A kind of entry is defined by "label",
 * the list of common labels you can see in the RFC's section 4.
 * Also see most-usable constants in this class named LABEL_*.
 */
public struct PemEntry <: ToString {
    public PemEntry(
        public let label: String,
        public let headers: Array<(String, String)>,
        public let body: ?DerBlob
    ) {
        validateLabel(unsafe { label.rawData() })
    }

    public init(label: String, body: DerBlob) {
        this(label, [], body)
    }

    /**
     * Returns values by header name (case sensitive)
     */
    public func header(name: String): Iterator<String> {
        return HeadersIterator(headers, name)
    }

    /**
     * Encode to a textual PEM format.
     *
     * @see Pem.encode()
     */
    public func encode(): String {
        Pem([this]).encode()
    }

    public override func toString(): String {
        let sb = StringBuilder()
        sb.append("PEM ")
        sb.append(label)
        sb.append(" (")
        match (body) {
            case Some(body) => sb.append(body.size.toString())
            case None => sb.append("0")
        }
        sb.append(" bytes)")
        return sb.toString()
    }

    public static let LABEL_CERTIFICATE: String = "CERTIFICATE"
    public static let LABEL_X509_CRL: String = "X509 CRL"
    public static let LABEL_CERTIFICATE_REQUEST: String = "CERTIFICATE REQUEST"
    public static let LABEL_PRIVATE_KEY: String = "PRIVATE KEY"
    public static let LABEL_EC_PRIVATE_KEY: String = "EC PRIVATE KEY"
    public static let LABEL_ENCRYPTED_PRIVATE_KEY: String = "ENCRYPTED PRIVATE KEY"
    public static let LABEL_RSA_PRIVATE_KEY: String = "RSA PRIVATE KEY"
    public static let LABEL_SM2_PRIVATE_KEY: String = "SM2 PRIVATE KEY"
    public static let LABEL_PUBLIC_KEY: String = "PUBLIC KEY"
    public static let LABEL_EC_PARAMETERS: String = "EC PARAMETERS"
    protected static let LABEL_DSA_PRIVATE_KEY: String = "DSA PRIVATE KEY"
    protected static let LABEL_TRUSTED_CERTIFICATE: String = "TRUSTED CERTIFICATE"
    public static let LABEL_DH_PARAMETERS: String = "DH PARAMETERS"
}

class HeadersIterator <: Iterator<String> {
    private var index = 0

    HeadersIterator(
        private let headers: Array<(String, String)>,
        private let name: String
    ) {}

    public override func next(): ?String {
        let size = headers.size
        let headers = headers
        while (index < size) {
            if (headers[index][0] == name) {
                let value = headers[index][1]
                index++
                return value
            }
            index++
        }
        return None
    }
}