"use strict";
// SPDX-License-Identifier: Apache-2.0
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const EmptyValue_1 = require("../../../core/error/EmptyValue");
const InvalidLength_1 = require("./error/InvalidLength");
const InvalidRange_1 = require("./error/InvalidRange");
const InvalidFormatHedera_1 = require("../../../domain/context/shared/error/InvalidFormatHedera");
const InvalidType_1 = require("./error/InvalidType");
const PublicKey_1 = __importDefault(require("../../../domain/context/account/PublicKey"));
const CheckStrings_1 = __importDefault(require("../../../core/checks/strings/CheckStrings"));
const CheckNums_1 = __importDefault(require("../../../core/checks/numbers/CheckNums"));
const AccountIdNotValid_1 = require("../../../domain/context/account/error/AccountIdNotValid");
const BigDecimal_1 = __importDefault(require("../../../domain/context/shared/BigDecimal"));
const Account_1 = __importDefault(require("../../../domain/context/account/Account"));
const ContractId_1 = __importDefault(require("../../../domain/context/contract/ContractId"));
const InvalidDecimalRange_1 = __importDefault(require("../../../domain/context/security/error/values/InvalidDecimalRange"));
const SecurityRole_1 = require("../../../domain/context/security/SecurityRole");
const InvalidRole_1 = require("../../../domain/context/security/error/values/InvalidRole");
const Constants_1 = require("../../../core/Constants");
const InvalidEvmAddress_1 = require("../../../domain/context/contract/error/InvalidEvmAddress");
const InvalidFormatHederaIdOrEvmAddress_1 = require("../../../domain/context/shared/error/InvalidFormatHederaIdOrEvmAddress");
const InvalidBytes32_1 = require("./error/InvalidBytes32");
const InvalidBytes3_1 = require("./error/InvalidBytes3");
const HederaId_1 = require("../../../domain/context/shared/HederaId");
const InvalidBytes_1 = require("./error/InvalidBytes");
const InvalidBase64_1 = require("./error/InvalidBase64");
const InvalidValue_1 = require("./error/InvalidValue");
class FormatValidation {
    static checkPublicKey = () => {
        return (val) => {
            const key = val;
            return PublicKey_1.default.validate(key);
        };
    };
    static checkContractId = () => {
        return (val) => {
            return ContractId_1.default.validate(val);
        };
    };
    static checkString = ({ max = Number.MAX_VALUE, min = 0, emptyCheck = true }) => {
        return (val) => {
            const err = [];
            if (typeof val !== "string") {
                err.push(new InvalidType_1.InvalidType(val));
            }
            else {
                if (emptyCheck && !CheckStrings_1.default.isNotEmpty(val)) {
                    err.push(new EmptyValue_1.EmptyValue(val));
                }
                else if (!CheckStrings_1.default.isLengthBetween(val, min, max)) {
                    err.push(new InvalidLength_1.InvalidLength(val, min, max));
                }
            }
            return err;
        };
    };
    static checkNumber = ({ max, min } = {}) => {
        return (val) => {
            const err = [];
            const iMax = max || max === 0;
            const iMin = min || min === 0;
            const isBigDecimal = CheckNums_1.default.isBigDecimal(val);
            if (typeof val !== "number" && !isBigDecimal) {
                err.push(new InvalidType_1.InvalidType(val));
            }
            else {
                let v = val;
                if (typeof v !== "number" && !(v instanceof BigDecimal_1.default))
                    v = BigDecimal_1.default.fromString(v);
                if (iMin && !iMax) {
                    if (CheckNums_1.default.isLessThan(v, min)) {
                        err.push(new InvalidRange_1.InvalidRange(v, min));
                    }
                }
                else if (!iMin && iMax) {
                    if (CheckNums_1.default.isGreaterThan(v, max)) {
                        err.push(new InvalidRange_1.InvalidRange(v, undefined, max));
                    }
                }
                else if (iMin && iMax) {
                    if (!CheckNums_1.default.isWithinRange(v, min, max)) {
                        err.push(new InvalidRange_1.InvalidRange(v, min, max));
                    }
                }
            }
            return err;
        };
    };
    static checkArrayNumber = ({ max, min } = {}) => {
        return (val) => {
            const err = [];
            const check = this.checkNumber({ max, min });
            for (const v of val) {
                const e = check(v);
                if (e.length > 0) {
                    err.push(...e);
                }
            }
            return err;
        };
    };
    static checkRole = () => {
        return (val) => {
            const err = [];
            const roles = Object.values(SecurityRole_1.SecurityRole);
            if (!roles.includes(val)) {
                err.push(new InvalidRole_1.InvalidRole(val));
            }
            return err;
        };
    };
    static checkAccount = () => {
        return (val) => {
            const { accountId, publicKey, evmAddress } = val;
            if (publicKey) {
                new Account_1.default({
                    id: accountId,
                    publicKey: new PublicKey_1.default(publicKey),
                    evmAddress,
                });
            }
            else {
                new Account_1.default({
                    id: accountId,
                    evmAddress,
                });
            }
        };
    };
    static checkHederaIdFormat = (zeroIsValid = false) => {
        return (val) => {
            // Account Id defined in hip-15 : https://hips.hedera.com/hip/hip-15
            const err = [];
            if (!HederaId_1.HEDERA_FORMAT_ID_REGEX.exec(val)) {
                err.push(new InvalidFormatHedera_1.InvalidFormatHedera(val));
            }
            else if (!zeroIsValid && val === "0.0.0") {
                err.push(new AccountIdNotValid_1.AccountIdNotValid(val));
            }
            return err;
        };
    };
    static checkEvmAddressFormat = (zeroIsValid = false) => {
        return (val) => {
            const evmAddressRegEx = /^0x[a-fA-F0-9]{40}$/;
            const err = [];
            if (!evmAddressRegEx.exec(val)) {
                err.push(new InvalidEvmAddress_1.InvalidEvmAddress(val));
            }
            else if (!zeroIsValid && val === Constants_1.EVM_ZERO_ADDRESS) {
                err.push(new AccountIdNotValid_1.AccountIdNotValid(val));
            }
            return err;
        };
    };
    static checkHederaIdFormatOrEvmAddress = (zeroIsValid = false) => {
        return (val) => {
            // Account Id defined in hip-15 : https://hips.hedera.com/hip/hip-15
            const evmAddressRegEx = /^0x[a-fA-F0-9]{40}$/;
            const err = [];
            if (!HederaId_1.HEDERA_FORMAT_ID_REGEX.exec(val) && !evmAddressRegEx.exec(val)) {
                err.push(new InvalidFormatHederaIdOrEvmAddress_1.InvalidFormatHederaIdOrEvmAddress(val));
            }
            else if (!zeroIsValid && (val === "0.0.0" || val === Constants_1.EVM_ZERO_ADDRESS)) {
                err.push(new AccountIdNotValid_1.AccountIdNotValid(val));
            }
            return err;
        };
    };
    static checkAmount = (zeroIsValid = false, decimals = 18) => {
        return (val) => {
            const err = [];
            const isBigDecimal = CheckNums_1.default.isBigDecimal(val);
            if (!isBigDecimal) {
                err.push(new InvalidType_1.InvalidType(val));
                return err;
            }
            const valueDecimals = BigDecimal_1.default.getDecimalsFromString(val);
            const zero = BigDecimal_1.default.fromString("0", valueDecimals);
            const value = BigDecimal_1.default.fromString(val);
            if (zeroIsValid && value.isLowerThan(zero))
                err.push(new InvalidRange_1.InvalidRange(val, "0", undefined));
            else if (!zeroIsValid && value.isLowerOrEqualThan(zero))
                err.push(new InvalidRange_1.InvalidRange(val, "0", undefined));
            if (valueDecimals > decimals) {
                err.push(new InvalidDecimalRange_1.default(val, 0, decimals));
            }
            return err;
        };
    };
    static checkBytes32Format = () => {
        return (val) => {
            const bytes32RegEx = /^0x[a-fA-F0-9]{64}$/;
            const err = [];
            if (!bytes32RegEx.exec(val)) {
                err.push(new InvalidBytes32_1.InvalidBytes32(val));
            }
            return err;
        };
    };
    static checkBytes3Format = () => {
        return (val) => {
            const bytes3RegEx = /^0x[a-fA-F0-9]{6}$/;
            const err = [];
            if (!bytes3RegEx.exec(val)) {
                err.push(new InvalidBytes3_1.InvalidBytes3(val));
            }
            return err;
        };
    };
    static checkBytesFormat = () => {
        return (val) => {
            const bytesRegEx = /^0x([a-fA-F0-9][a-fA-F0-9])*$/;
            const err = [];
            if (!bytesRegEx.exec(val)) {
                err.push(new InvalidBytes_1.InvalidBytes(val));
            }
            return err;
        };
    };
    static checkBase64Format = () => {
        return (val) => {
            const base64RegEx = /^[a-zA-Z0-9+/]*={0,2}$/;
            const err = [];
            if (!base64RegEx.exec(val)) {
                err.push(new InvalidBase64_1.InvalidBase64(val));
            }
            return err;
        };
    };
    static checkHederaIdOrEvmAddressArray(values, fieldName, allowEmpty = false) {
        if (values.length === 0) {
            return allowEmpty ? [] : [new InvalidValue_1.InvalidValue(`The list of ${fieldName} cannot be empty`)];
        }
        const errors = [];
        const seenValues = new Set();
        values.forEach((value) => {
            const formatErrors = FormatValidation.checkHederaIdFormatOrEvmAddress()(value);
            errors.push(...formatErrors);
            if (seenValues.has(value)) {
                errors.push(new InvalidValue_1.InvalidValue(`${fieldName} ${value} is duplicated`));
            }
            seenValues.add(value);
        });
        return errors;
    }
    static checkBoolean = () => {
        return (val) => {
            const err = [];
            if (typeof val !== "boolean") {
                err.push(new InvalidType_1.InvalidType(val));
            }
            return err;
        };
    };
}
exports.default = FormatValidation;
