import { base64ToBuffer, bufferToBase64 } from '../lib/Buffer.js';
import { nanoid } from '../nanoid.js';
export const Kind = 'Core#Certificate';
/**
 * A class that represents a certificate in the system
 */
export class Certificate {
    kind = Kind;
    /**
     * The data store key to refer.
     */
    key;
    /**
     * Custom name of the certificate.
     */
    name;
    /**
     * Timestamp when the certificate was inserted into the data store.
     * Required when returning a result. Auto-generated when inserting, if missing.
     */
    created = 0;
    /**
     * Certificate type. Either `p12` or `pem`.
     */
    type;
    /**
     * Certificate or list of certificates to use.
     */
    cert;
    /**
     * The key for the `pem` type certificate.
     */
    certKey;
    /**
     * Creates a new certificate instance for a PEM key
     *
     * @param pem The certificate contents
     * @param key The key contents
     * @param name The certificate name
     * @param keyPassphrase The key passphrase
     */
    static fromPem(pem, key, name = 'New PEM certificate', keyPassphrase) {
        const init = {
            kind: Kind,
            cert: {
                data: pem,
            },
            certKey: {
                data: key,
            },
            key: nanoid(),
            name,
            type: 'pem',
            created: Date.now(),
        };
        if (keyPassphrase) {
            init.certKey.passphrase = keyPassphrase;
        }
        return new Certificate(init);
    }
    /**
     * Creates a new certificate instance for a P12 key
     *
     * @param cert The certificate contents
     * @param name The certificate name
     * @param passphrase The key passphrase
     */
    static fromP12(cert, name = 'New P12 certificate', passphrase) {
        const init = {
            kind: Kind,
            cert: {
                data: cert,
            },
            key: nanoid(),
            name,
            type: 'p12',
            created: Date.now(),
        };
        if (passphrase) {
            init.cert.passphrase = passphrase;
        }
        return new Certificate(init);
    }
    /**
     * Creates a certificate object from the ARC's legacy certificate definition.
     *
     * @param index The legacy certificate index object. If it has set `_id` it will be used as the `key`.
     * @param index The certificate data object as read from the data store. Do not restore the data
     *              to its original format.
     */
    static fromLegacy(index, cert) {
        const { name = '', type, created = Date.now(), _id = nanoid() } = index;
        if (type === 'pem') {
            const data = Array.isArray(cert.cert) ? cert.cert[0] : cert.cert;
            const key = Array.isArray(cert.key) ? cert.key[0] : cert.key;
            if (!key) {
                throw new Error(`Unable to create a PEM certificate without the key.`);
            }
            const init = {
                kind: Kind,
                cert: data, // these are compatible.
                certKey: key,
                key: _id,
                name,
                type: 'pem',
                created,
            };
            return new Certificate(init);
        }
        else if (type === 'p12') {
            const data = Array.isArray(cert.cert) ? cert.cert[0] : cert.cert;
            const init = {
                kind: Kind,
                cert: data, // these are compatible.
                key: _id,
                name,
                type: 'p12',
                created,
            };
            return new Certificate(init);
        }
        throw new Error(`Unable to create a certificate. Unknown type: ${type}.`);
    }
    constructor(certificate) {
        const { type, cert, key = nanoid(), name = '', created = Date.now() } = certificate;
        this.key = key;
        this.name = name;
        this.type = type;
        this.cert = Certificate.fromStore(cert);
        this.created = created;
        if (type === 'pem') {
            const typed = certificate;
            this.certKey = Certificate.fromStore(typed.certKey);
        }
    }
    /**
     * When needed it reads the certificate's original format.
     * @param data The certificate data.
     * @returns The restored certificate.
     */
    static fromStore(data) {
        if (data.type) {
            delete data.type;
            const content = data.data;
            data.data = base64ToBuffer(content);
        }
        return data;
    }
    /**
     * Prepares certificate object to be stored in the data store.
     * If the `data` property is not string then it assumes buffer (either
     * Node's or ArrayBuffer). In this case it converts buffer to base64 string.
     * It also adds `type` property set to `buffer` for the `fromStore()`
     * function to recognize what to do with the data.
     *
     * Note, for optimization, PEM keys should be strings as the content of the
     * certificate is already a base62 string. To spare double base64 conversion
     * use string data.
     *
     * @param data The certificate data object.
     * @throws When data is not set
     */
    static toStore(data) {
        if (!data) {
            throw new Error('Certificate data is missing.');
        }
        if (!data.data) {
            throw new Error('Certificate content not set.');
        }
        if (typeof data.data !== 'string') {
            data.type = 'buffer';
            const buff = data.data;
            data.data = bufferToBase64(buff);
        }
        return data;
    }
    toJSON() {
        const result = {
            kind: Kind,
            key: this.key,
            cert: Certificate.toStore(this.cert),
            name: this.name,
            type: this.type,
            created: this.created,
        };
        if (this.type === 'pem' && this.certKey) {
            const typed = result;
            typed.certKey = Certificate.toStore(this.certKey);
        }
        return result;
    }
}
//# sourceMappingURL=ClientCertificate.js.map