"use strict";
// SPDX-License-Identifier: Apache-2.0
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Security = void 0;
const CheckNums_1 = __importDefault(require("../../../core/checks/numbers/CheckNums"));
const CheckStrings_1 = __importDefault(require("../../../core/checks/strings/CheckStrings"));
const InvalidDecimalRange_1 = __importDefault(require("./error/values/InvalidDecimalRange"));
const NameEmpty_1 = __importDefault(require("./error/values/NameEmpty"));
const NameLength_1 = __importDefault(require("./error/values/NameLength"));
const SymbolEmpty_1 = __importDefault(require("./error/values/SymbolEmpty"));
const SymbolLength_1 = __importDefault(require("./error/values/SymbolLength"));
const BigDecimal_1 = __importDefault(require("../shared/BigDecimal"));
const InvalidType_1 = require("../../../port/in/request/error/InvalidType");
const InvalidAmount_1 = __importDefault(require("./error/values/InvalidAmount"));
const RegulationType_1 = require("../factory/RegulationType");
const ValidatedArgs_1 = __importDefault(require("../../../core/validation/ValidatedArgs"));
const Factories_1 = require("../factory/Factories");
const OptionalDecorator_1 = require("../../../core/decorator/OptionalDecorator");
const InvalidSupply_1 = __importDefault(require("./error/values/InvalidSupply"));
const TWELVE = 12;
const TEN = 10;
const ONE_HUNDRED = 100;
const EIGHTEEN = 18;
const ZERO = 0;
class Security extends ValidatedArgs_1.default {
    name;
    symbol;
    isin;
    type;
    decimals;
    isWhiteList;
    erc20VotesActivated;
    isControllable;
    isMultiPartition;
    arePartitionsProtected;
    clearingActive;
    internalKycActivated;
    isIssuable;
    totalSupply;
    maxSupply;
    diamondAddress;
    evmDiamondAddress;
    paused;
    regulationType;
    regulationsubType;
    regulation;
    isCountryControlListWhiteList;
    countries;
    info;
    constructor(params) {
        super({
            regulationType: (val) => {
                return Factories_1.Factory.checkRegulationType(RegulationType_1.CastRegulationType.toNumber(val));
            },
            regulationsubType: (val) => {
                return Factories_1.Factory.checkRegulationSubType(RegulationType_1.CastRegulationSubType.toNumber(val), RegulationType_1.CastRegulationType.toNumber(this.regulationType));
            },
            totalSupply: (val) => {
                return Security.checkSupply(val, this.maxSupply);
            },
        });
        const { name, symbol, isin, type, decimals, isWhiteList, erc20VotesActivated, isControllable, arePartitionsProtected, clearingActive, internalKycActivated, isMultiPartition, isIssuable, totalSupply, maxSupply, diamondAddress, evmDiamondAddress, paused, regulationType, regulationsubType, regulation, isCountryControlListWhiteList, countries, info, } = params;
        this.name = name;
        this.symbol = symbol;
        this.isin = isin;
        this.type = type;
        this.decimals = decimals;
        this.isWhiteList = isWhiteList;
        this.erc20VotesActivated = erc20VotesActivated;
        this.isControllable = isControllable;
        this.arePartitionsProtected = arePartitionsProtected;
        this.clearingActive = clearingActive;
        this.internalKycActivated = internalKycActivated;
        this.isMultiPartition = isMultiPartition;
        this.isIssuable = isIssuable ?? true;
        this.totalSupply = totalSupply ?? BigDecimal_1.default.ZERO;
        this.maxSupply = maxSupply ?? BigDecimal_1.default.ZERO;
        this.diamondAddress = diamondAddress;
        this.evmDiamondAddress = evmDiamondAddress;
        this.paused = paused ?? false;
        this.regulationType = regulationType;
        this.regulationsubType = regulationsubType;
        this.regulation = regulation;
        this.isCountryControlListWhiteList = isCountryControlListWhiteList;
        this.countries = countries;
        this.info = info;
        ValidatedArgs_1.default.handleValidation(Security.name, this);
    }
    static checkName(value) {
        const maxNameLength = ONE_HUNDRED;
        const errorList = [];
        if (!CheckStrings_1.default.isNotEmpty(value))
            errorList.push(new NameEmpty_1.default());
        if (!CheckStrings_1.default.isLengthUnder(value, maxNameLength))
            errorList.push(new NameLength_1.default(value, maxNameLength));
        return errorList;
    }
    static checkSymbol(value) {
        const maxSymbolLength = ONE_HUNDRED;
        const errorList = [];
        if (!CheckStrings_1.default.isNotEmpty(value))
            errorList.push(new SymbolEmpty_1.default());
        if (!CheckStrings_1.default.isLengthUnder(value, maxSymbolLength))
            errorList.push(new SymbolLength_1.default(value, maxSymbolLength));
        return errorList;
    }
    static checkISIN(value) {
        const maxIsinLength = TWELVE;
        const errorList = [];
        if (!CheckStrings_1.default.isNotEmpty(value))
            errorList.push(new NameEmpty_1.default());
        if (!CheckStrings_1.default.isLengthUnder(value, maxIsinLength))
            errorList.push(new NameLength_1.default(value, maxIsinLength));
        return errorList;
    }
    static checkDecimals(value) {
        const errorList = [];
        const min = ZERO;
        const max = EIGHTEEN;
        if (CheckNums_1.default.hasMoreDecimals(value.toString(), 0)) {
            errorList.push(new InvalidType_1.InvalidType(value));
        }
        if (!CheckNums_1.default.isWithinRange(value, min, max))
            errorList.push(new InvalidDecimalRange_1.default(value, min, max));
        return errorList;
    }
    static checkInteger(value) {
        const errorList = [];
        if (!Number.isInteger(value)) {
            return [new InvalidType_1.InvalidType(value)];
        }
        return errorList;
    }
    getDecimalOperator() {
        return TEN ** this.decimals;
    }
    fromInteger(amount) {
        const res = amount / this.getDecimalOperator();
        if (!this.isValidAmount(res)) {
            throw new InvalidAmount_1.default(res, this.decimals);
        }
        return res;
    }
    isValidAmount(amount) {
        const val = amount.toString().split(".");
        const decimals = val.length > 1 ? val[1]?.length : 0;
        return decimals <= this.decimals;
    }
    static checkSupply(totalSupply, maxSupply) {
        const errorList = [];
        if (totalSupply.isGreaterThan(maxSupply)) {
            errorList.push(new InvalidSupply_1.default(totalSupply.toString(), maxSupply.toString()));
        }
        return errorList;
    }
}
exports.Security = Security;
__decorate([
    (0, OptionalDecorator_1.OptionalField)(),
    __metadata("design:type", BigDecimal_1.default)
], Security.prototype, "totalSupply", void 0);
__decorate([
    (0, OptionalDecorator_1.OptionalField)(),
    __metadata("design:type", BigDecimal_1.default)
], Security.prototype, "maxSupply", void 0);
__decorate([
    (0, OptionalDecorator_1.OptionalField)(),
    __metadata("design:type", String)
], Security.prototype, "regulationType", void 0);
__decorate([
    (0, OptionalDecorator_1.OptionalField)(),
    __metadata("design:type", String)
], Security.prototype, "regulationsubType", void 0);
