import { kinds } from "nostr-tools";
import { isEvent, notifyEventUpdate } from "./event.js";
/** A symbol use to store the encrypted content of an event in memory */
export const EncryptedContentSymbol = Symbol.for("encrypted-content");
/** Various event kinds that can have encrypted content and which encryption method they use */
export const EventContentEncryptionMethod = {
    [kinds.EncryptedDirectMessage]: "nip04",
    [kinds.Seal]: "nip44",
    [kinds.GiftWrap]: "nip44",
};
/** Sets the encryption method that is used for the contents of a specific event kind */
export function setEncryptedContentEncryptionMethod(kind, method) {
    EventContentEncryptionMethod[kind] = method;
    return kind;
}
/**
 * Returns either nip04 or nip44 encryption methods depending on event kind
 * @param kind The event kind to get the encryption method for
 * @param signer The signer to use to get the encryption methods
 * @param override The encryption method to use instead of the default
 * @throws If the event kind does not support encrypted content
 * @throws If the signer does not support the encryption method
 * @returns The encryption methods for the event kind
 */
export function getEncryptedContentEncryptionMethods(kind, signer, override) {
    const method = override ?? EventContentEncryptionMethod[kind];
    if (!method)
        throw new Error(`Event kind ${kind} does not support encrypted content`);
    const encryption = signer[method];
    if (!encryption)
        throw new Error(`Signer does not support ${method} encryption`);
    return encryption;
}
/** Checks if an event can have encrypted content */
export function canHaveEncryptedContent(kind) {
    return EventContentEncryptionMethod[kind] !== undefined;
}
/** Checks if an event has encrypted content */
export function hasEncryptedContent(event) {
    return event.content.length > 0;
}
/** Returns the encrypted content for an event if it is unlocked */
export function getEncryptedContent(event) {
    return Reflect.get(event, EncryptedContentSymbol);
}
/** Checks if the encrypted content is locked */
export function isEncryptedContentLocked(event) {
    return Reflect.has(event, EncryptedContentSymbol) === false;
}
/**
 * Unlocks the encrypted content in an event and caches it
 * @param event The event with content to decrypt
 * @param pubkey The other pubkey that encrypted the content
 * @param signer A signer to use to decrypt the content
 */
export async function unlockEncryptedContent(event, pubkey, signer) {
    const encryption = getEncryptedContentEncryptionMethods(event.kind, signer);
    const plaintext = await encryption.decrypt(pubkey, event.content);
    setEncryptedContentCache(event, plaintext);
    return plaintext;
}
/** Sets the encrypted content on an event and updates it if its part of an event store */
export function setEncryptedContentCache(event, plaintext) {
    Reflect.set(event, EncryptedContentSymbol, plaintext);
    // if the event has been added to an event store, notify it
    if (isEvent(event))
        notifyEventUpdate(event);
}
/** Removes the encrypted content cache on an event */
export function lockEncryptedContent(event) {
    Reflect.deleteProperty(event, EncryptedContentSymbol);
    // if the event has been added to an event store, notify it
    if (isEvent(event))
        notifyEventUpdate(event);
}
