/**
 * @module encrypt helper/util/etc. functions
 *
 * this is where you will find helper functions like those that generate
 * and parse ibs for encryption ibgibs.
 */
// import * as pathUtils from 'path';
// import { statSync } from 'node:fs';
// import { readFile, } from 'node:fs/promises';
// import * as readline from 'node:readline/promises';
// import { stdin, stdout } from 'node:process'; // decide if use this or not
import { extractErrorMsg, } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
import { CLASSNAME_REGEXP, UUID_REGEXP, } from '@ibgib/helper-gib/dist/constants.mjs';
import { HASH_ALGORITHMS, SALT_STRATEGIES } from '@ibgib/encrypt-gib/dist/types.mjs';
import { validateIbGibIntrinsically } from '@ibgib/ts-gib/dist/V1/validate-helper.mjs';
import { Factory_V1 } from "@ibgib/ts-gib/dist/V1/factory.mjs";
import { GLOBAL_LOG_A_LOT } from "../../core-constants.mjs";
import { EncryptionMethod, VALID_ENCRYPTION_METHODS, } from './encrypt-types.mjs';
import { ENCRYPTION_REL8N_NAME, ENCRYPTION_ATOM, ENCRYPTION_NAME_REGEXP, } from './encrypt-constants.mjs';
import { SpecialIbGibType } from '../other/other-types.mjs';
/**
 * for verbose logging
 */
const logalot = GLOBAL_LOG_A_LOT;
export function validateCommonEncryptionData({ data, }) {
    const lc = `[${validateCommonEncryptionData.name}]`;
    try {
        if (logalot) {
            console.log(`${lc} starting...`);
        }
        if (!data) {
            throw new Error(`data required (E: 9c7e015ad86041da89fa0a8490b19496)`);
        }
        const errors = [];
        const { name, uuid, classname, method, } = data;
        if (name) {
            if (!name.match(ENCRYPTION_NAME_REGEXP)) {
                errors.push(`name must match regexp: ${ENCRYPTION_NAME_REGEXP} (E: 3408de089b194553a1b9d2eb49fdda1c)`);
            }
        }
        else {
            errors.push(`name required. (E: 1f4ec2f886a142279a91f852a13c3225)`);
        }
        if (method) {
            if (!VALID_ENCRYPTION_METHODS.includes(method)) {
                errors.push(`method (${method}) is invalid. must be one of ${VALID_ENCRYPTION_METHODS.join(', ')} (E: 84a382b525944082badae40aebed497d)`);
            }
        }
        else {
            errors.push(`method required. (E: 0bf6177233b24c9fa98499dc1453c0c9)`);
        }
        if (uuid) {
            if (!uuid.match(UUID_REGEXP)) {
                errors.push(`uuid must match regexp: ${UUID_REGEXP} (E: bf54ee4ac10a4ee3a8fd1f5db17f1866)`);
            }
        }
        if (classname) {
            if (!classname.match(CLASSNAME_REGEXP)) {
                errors.push(`classname must match regexp: ${CLASSNAME_REGEXP} (E: 054087390a2d40daa6955e70e31c0cdb)`);
            }
        }
        if (method === EncryptionMethod.encrypt_gib) {
            const encryptGibErrors = validateCommonEncryptionData_encryptGib({ data });
            encryptGibErrors.forEach(x => errors.push(x));
        }
        return errors;
    }
    catch (error) {
        console.error(`${lc} ${extractErrorMsg(error)}`);
        throw error;
    }
    finally {
        if (logalot) {
            console.log(`${lc} complete.`);
        }
    }
}
function validateCommonEncryptionData_encryptGib({ data, }) {
    const lc = `[${validateCommonEncryptionData_encryptGib.name}]`;
    try {
        if (logalot) {
            console.log(`${lc} starting... (I: 2da8272bd687b2c488a4af0c592b1524)`);
        }
        const errors = [];
        if (data.encryptedDataDelimiter) {
            if (typeof data.encryptedDataDelimiter !== 'string') {
                errors.push(`encryptedDataDelimiter must be string (E: fcd4f6b27a084b219244cfbab641f840)`);
            }
        }
        if (data.hashAlgorithm) {
            if (!HASH_ALGORITHMS.includes(data.hashAlgorithm)) {
                errors.push(`invalid hashAlgorithm (${data.hashAlgorithm}). must be one of ${HASH_ALGORITHMS}. (E: 5f7a75b2d1164e07b10a78adc155774a)`);
            }
        }
        if (data.initialRecursions) {
            if (typeof data.initialRecursions !== 'number') {
                errors.push(`invalid initialRecursions (${data.initialRecursions}, typeof: ${typeof data.initialRecursions}). must be type "number" (E: 03c3f5fae9fe48bf92bb82ec806fa293)`);
            }
            else if (data.initialRecursions < 0) {
                errors.push(`invalid dataRecursions (${data.initialRecursions}). must be positive integer or 0. (E: a12658e792c8448a9b31d8e0b001a1b2)`);
            }
        }
        else {
            errors.push(`initialRecursions required. (E: bb14b31042074f9aad4ed8fc08846c62)`);
        }
        if (data.recursionsPerHash) {
            if (typeof data.recursionsPerHash !== 'number') {
                errors.push(`invalid recursionsPerHash (${data.recursionsPerHash}, typeof: ${typeof data.recursionsPerHash}). must be type "number" (E: b373d88bf22043408c1da42df9902211)`);
            }
            else if (data.recursionsPerHash <= 0) {
                errors.push(`invalid recursionsPerHash (${data.recursionsPerHash}). must be positive integer. (E: 7eec3ccd22ed4bbf96c06479e2de02b7)`);
            }
        }
        if (data.salt || data.salt === '') {
            if (typeof data.salt !== 'string') {
                errors.push(`invalid salt (${data.salt}, typeof: ${typeof data.salt}). must be "string". (E: 0bee1f049dfd4f6e937cd423bb1b0c90)`);
            }
        }
        else {
            errors.push(`salt required. (E: 7ee8e2a760184999b13e7966a8057b2b)`);
        }
        if (data.saltStrategy) {
            if (!SALT_STRATEGIES.includes(data.saltStrategy)) {
                errors.push(`invalid saltStrategy (${data.saltStrategy}). must be one of ${SALT_STRATEGIES}. (E: 7da81150e5144c448876e950e373e7e5)`);
            }
        }
        if (data.blockMode) {
            if (data.blockModeOptions) {
                const { maxBlockSize, numOfPasses, maxPassSectionLength } = data.blockModeOptions;
                if (typeof maxBlockSize === 'number' && maxBlockSize > 0) {
                    // valid
                }
                else if (typeof maxBlockSize !== 'number') {
                    errors.push(`maxBlockSize must be a number (E: 38445d8d6794448a8bf26a62d5743582)`);
                }
                else {
                    errors.push(`maxBlockSize (${maxBlockSize}) must be a positive integer. (E: 59b484999aec43e39f7da295dbfbc09b)`);
                }
                if (!!maxBlockSize || (typeof maxPassSectionLength === 'number' && maxPassSectionLength > 0)) {
                    // valid
                }
                else if (typeof maxPassSectionLength !== 'number') {
                    errors.push(`maxPassSectionLength must be a number (also this is deprecatd, use maxBlockSize) (E: dc55a206d4dc4907b7de4c1a2ff8b70a)`);
                }
                else {
                    errors.push(`maxPassSectionLength (${maxPassSectionLength}) must be a positive integer. (also this is deprecatd, use maxBlockSize) (E: 25eb5682b42d4a52aa64e1c52552c885)`);
                }
                if (typeof numOfPasses === 'number' && numOfPasses > 0) {
                    // valid
                }
                else if (typeof numOfPasses !== 'number') {
                    errors.push(`numOfPasses must be a number (E: 945ec18134324128aac42dfc444cbdf6)`);
                }
                else {
                    errors.push(`numOfPasses (${numOfPasses}) must be a positive integer. (E: c4ee94680460469cb3bb3d0da13addc1)`);
                }
            }
            else {
                errors.push(`blockMode is truthy but blockModeOptions is falsy? blockModeOptions are required when blockMode is set. (E: 71bd745707e2434e9338451ae31320a5)`);
            }
        }
        return errors;
    }
    catch (error) {
        console.error(`${lc} ${extractErrorMsg(error)}`);
        throw error;
    }
    finally {
        if (logalot) {
            console.log(`${lc} complete.`);
        }
    }
}
export async function validateCommonEncryptionIbGib({ ibGib, }) {
    const lc = `[${validateCommonEncryptionIbGib.name}]`;
    try {
        if (logalot) {
            console.log(`${lc} starting... (I: 48b13b0fe20146258ee921ed22a214d9)`);
        }
        const intrinsicErrors = await validateIbGibIntrinsically({ ibGib: ibGib }) ?? [];
        if (!ibGib.data) {
            throw new Error(`EncryptionIbGib.data required (E: bdc7bbea44e042118352f4fa512fea43)`);
        }
        const ibErrors = [];
        // ib
        let { atom, method, name, } = parseEncryptionIb({ ib: ibGib.ib });
        if (atom !== ENCRYPTION_ATOM) {
            ibErrors.push(`invalid encryption atom. must be ${ENCRYPTION_ATOM} (E: 8437377bc6b548db846b8802e935812d)`);
        }
        if (!method) {
            ibErrors.push(`encryption method required (E: b19999f74eff4d7da15867ba5907876b)`);
        }
        if (!name) {
            ibErrors.push(`encryption name required (E: ae9bdc064f804f4a86f157cfe58274f7)`);
        }
        // data
        const dataErrors = validateCommonEncryptionData({ data: ibGib.data });
        let result = [...(intrinsicErrors ?? []), ...(ibErrors ?? []), ...(dataErrors ?? [])];
        if (result.length > 0) {
            return result;
        }
        else {
            return undefined;
        }
    }
    catch (error) {
        console.error(`${lc} ${extractErrorMsg(error)}`);
        throw error;
    }
    finally {
        if (logalot) {
            console.log(`${lc} complete.`);
        }
    }
}
/**
 * builds the ib based on data.
 *
 * atow (02/2024) this is only data.name and data.method.
 *
 * @returns `${ENCRYPTION_ATOM} ${method} ${name}` atow (02/2024)
 */
export function getEncryptionIb({ data, }) {
    const lc = `[${getEncryptionIb.name}]`;
    try {
        const validationErrors = validateCommonEncryptionData({ data });
        if (validationErrors.length > 0) {
            throw new Error(`invalid Encryption data: ${validationErrors} (E: f2f124c1b55a496c835849cc9e67a96f)`);
        }
        const { name, method } = data;
        return `${ENCRYPTION_ATOM} ${method} ${name}`;
    }
    catch (error) {
        console.error(`${lc} ${extractErrorMsg(error)}`);
        throw error;
    }
}
/**
 * Current schema is `${ENCRYPTION_ATOM} ${method} ${name}`
 *
 * NOTE this is space-delimited
 */
export function parseEncryptionIb({ ib, }) {
    const lc = `[${parseEncryptionIb.name}]`;
    try {
        if (!ib) {
            throw new Error(`Encryption ib required (E: 067fb72027f34ddc95dfba76fd429ed4)`);
        }
        const [atom, method, name] = ib.split(' ');
        if (atom !== ENCRYPTION_ATOM) {
            throw new Error(`atom !== ${ENCRYPTION_ATOM} (E: 8361b9630e3f4f309ce48f1db278cc74)`);
        }
        if (method !== EncryptionMethod.encrypt_gib) {
            console.warn(`${lc} method (${method})!== EncryptionMethod.encrypt_gib. atow (02/2024) EncryptionMethod.encrypt_gib is the only thing we got. (W: 266540fa139544079e313e12d707aafe)`);
        }
        if (!name.match(ENCRYPTION_NAME_REGEXP)) {
            throw new Error(`!name.match(ENCRYPTION_NAME_REGEXP) (E: 5a49f74179d44b83a4cb4310e05cb2e3)`);
        }
        return { atom, method, name, };
    }
    catch (error) {
        console.error(`${lc} ${extractErrorMsg(error)}`);
        throw error;
    }
}
export async function createAndRegisterNewEncryption({ encryptionMethod, encryptionInfo, metaspace, space, }) {
    const lc = `[${createAndRegisterNewEncryption.name}]`;
    try {
        if (logalot) {
            console.log(`${lc} starting... (I: 7839b94f046a43aebc2ac0ff350c464b)`);
        }
        let resEncryptionIbGib;
        if (encryptionMethod !== EncryptionMethod.encrypt_gib) {
            throw new Error(`unknown encryptionMethod (${encryptionMethod}). only "encrypt-gib" encryption method currently implemented. (E: bfc617eb731a4f99821fcdd3feba3835)`);
        }
        resEncryptionIbGib = await createAndRegisterNewEncryption_encryptGib({
            encryptionInfo: encryptionInfo,
            metaspace,
            space,
        });
        return resEncryptionIbGib;
    }
    catch (error) {
        console.error(`${lc} ${extractErrorMsg(error)}`);
        throw error;
    }
    finally {
        if (logalot) {
            console.log(`${lc} complete.`);
        }
    }
}
async function createAndRegisterNewEncryption_encryptGib({ encryptionInfo, metaspace, space, }) {
    const lc = `[${createAndRegisterNewEncryption_encryptGib.name}]`;
    try {
        if (logalot) {
            console.log(`${lc} starting... (I: 5413d44c92db43b0ab70afa962266828)`);
        }
        const { method: encryptionMethod } = encryptionInfo;
        if (encryptionMethod !== EncryptionMethod.encrypt_gib) {
            throw new Error(`(UNEXPECTED) encryptionMethod (${encryptionMethod}) !== ${EncryptionMethod.encrypt_gib}? (E: 5b1d1d2cd00e4ae1a759da2c4071b46d)`);
        }
        // create the encryption ibgib
        const data = {
            ...encryptionInfo,
        };
        const resFirstGen = await Factory_V1.firstGen({
            ib: getEncryptionIb({ data }),
            parentIbGib: Factory_V1.primitive({ ib: ENCRYPTION_ATOM }),
            data,
            dna: true,
            nCounter: true,
            tjp: { timestamp: true, },
        });
        const encryptionIbGib = resFirstGen.newIbGib;
        // validate right away before anything else
        const validationErrors = await validateCommonEncryptionIbGib({ ibGib: encryptionIbGib }) ?? [];
        if (validationErrors.length > 0) {
            throw new Error(`(UNEXPECTED) newly created encryptionIbGib has validationErrors? validationErrors: ${validationErrors} (E: 38791edd0b684eb58c6a194e055cadf9)`);
        }
        // save first in the space...
        await metaspace.persistTransformResult({ resTransform: resFirstGen, space });
        // register the new encryption with the ibgib space in general...
        await metaspace.registerNewIbGib({ ibGib: encryptionIbGib, space });
        // register the new encryption with the encryptions index
        await metaspace.rel8ToSpecialIbGib({
            type: SpecialIbGibType.encryptions,
            rel8nName: ENCRYPTION_REL8N_NAME,
            ibGibsToRel8: [encryptionIbGib],
            space,
        });
        return encryptionIbGib;
    }
    catch (error) {
        console.error(`${lc} ${extractErrorMsg(error)}`);
        throw error;
    }
    finally {
        if (logalot) {
            console.log(`${lc} complete.`);
        }
    }
}
//# sourceMappingURL=encrypt-helper.mjs.map