"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Property = void 0;
const types_1 = require("../types");
const cliter_config_1 = require("../config/cliter.config");
const faker = require("faker");
const yaml_manager_1 = require("./yaml-manager");
class Property {
    constructor(payload) {
        this.config = cliter_config_1.cliterConfig;
        this.id = faker.datatype.uuid();
        this._name = payload.name;
        this.type = payload.type;
        this.primaryKey = payload.primaryKey;
        this.autoIncrement = payload.autoIncrement;
        this._enumOptions = payload.enumOptions;
        this.decimals = payload.decimals;
        this.length = payload.length;
        this.minLength = payload.minLength;
        this.maxLength = payload.maxLength;
        this.nullable = payload.nullable;
        this.defaultValue = payload.defaultValue;
        this.relationship = payload.relationship;
        this.relationshipSingularName = payload.relationshipSingularName;
        this.relationshipAggregate = payload.relationshipAggregate;
        this.relationshipModulePath = payload.relationshipModulePath;
        this.relationshipKey = payload.relationshipKey;
        this.relationshipField = payload.relationshipField;
        this.relationshipAvoidConstraint = payload.relationshipAvoidConstraint;
        this.relationshipPackageName = payload.relationshipPackageName;
        this.pivotAggregateName = payload.pivotAggregateName;
        this.pivotPath = payload.pivotPath;
        this.pivotFileName = payload.pivotFileName;
        this.isDenormalized = payload.isDenormalized;
        this.index = payload.index;
        this.indexName = payload.indexName;
        this.isI18n = payload.isI18n;
        this.example = payload.example;
        this.faker = payload.faker;
        if ((this.type === types_1.SqlType.VARCHAR ||
            this.type === types_1.SqlType.TINYINT ||
            this.type === types_1.SqlType['TINYINT.UNSIGNED'] ||
            this.type === types_1.SqlType.INT ||
            this.type === types_1.SqlType['INT.UNSIGNED'] ||
            this.type === types_1.SqlType.SMALLINT ||
            this.type === types_1.SqlType['SMALLINT.UNSIGNED']) &&
            typeof this.length === 'number' && typeof this.maxLength !== 'number') {
            this.maxLength = this.length;
            this.length = undefined;
        }
        /*********************************************************************************
         * avoid set maxLength in decimal value object, this argument is already defined
         * example:
         *  - name: myColumn
         *   type: decimal
         *   decimals:
         *   - 11
         *   - 2
         *   nullable: false
         *********************************************************************************/
        if (this.type === types_1.SqlType.DECIMAL)
            this.maxLength = undefined;
    }
    // handlebars functions
    get hasTimezone() {
        return this.type === types_1.SqlType.TIMESTAMP;
    }
    get hasColumnDecorator() {
        return this.relationship !== types_1.SqlRelationship.ONE_TO_MANY &&
            this.relationship !== types_1.SqlRelationship.MANY_TO_MANY &&
            !(this.relationship === types_1.SqlRelationship.ONE_TO_ONE &&
                !this.relationshipField);
    }
    get hasHasOneDecorator() {
        return this.relationship === types_1.SqlRelationship.ONE_TO_ONE &&
            !this.relationshipField;
    }
    get hasBelongsToDecorator() {
        return (this.relationship === types_1.SqlRelationship.MANY_TO_ONE &&
            Boolean(this.relationshipField)) ||
            (this.relationship === types_1.SqlRelationship.ONE_TO_ONE &&
                Boolean(this.relationshipField));
    }
    get hasHasManyDecorator() {
        return this.relationship === types_1.SqlRelationship.ONE_TO_MANY;
    }
    get hasBelongsToManyDecorator() {
        return this.relationship === types_1.SqlRelationship.MANY_TO_MANY;
    }
    get getDefaultValue() {
        return typeof this.defaultValue === 'boolean' || typeof this.defaultValue === 'number' ? this.defaultValue : `'${this.defaultValue}'`;
    }
    get getReferenceKey() {
        return this.relationshipKey ? this.relationshipKey : 'id';
    }
    get isRelationship() {
        return Boolean(this.relationship);
    }
    get isBinary() {
        return this.type === types_1.SqlType.BLOB || this.type === types_1.SqlType.MEDIUMBLOB || this.type === types_1.SqlType.LONGBLOB;
    }
    // property names
    get originName() {
        return this._name;
    }
    get name() {
        // properties that represent many to many relationships, are arrays of ids
        if (this.relationship === types_1.SqlRelationship.MANY_TO_MANY)
            return `${this.relationshipSingularName}Ids`;
        return this._name;
    }
    get enumOptionsArrayItems() {
        var _a;
        return (_a = this.enumOptions) === null || _a === void 0 ? void 0 : _a.map(item => '\'' + item + '\'').join(',');
    }
    get enumOptions() {
        return typeof this._enumOptions === 'string' ? this._enumOptions.split(',').map(item => item.trim().toUpperCase()) : undefined;
    }
    get getRelationshipBoundedContext() {
        if (this.relationshipModulePath)
            return this.parseModuleSection(this.relationshipModulePath).boundedContextName;
        return null;
    }
    get getRelationshipModule() {
        if (this.relationshipModulePath)
            return this.parseModuleSection(this.relationshipModulePath).moduleName;
        return null;
    }
    get getRelationshipModules() {
        if (this.relationshipModulePath)
            return this.parseModuleSection(this.relationshipModulePath).moduleNames;
        return null;
    }
    get getJavascriptType() {
        if (this.relationship === types_1.SqlRelationship.MANY_TO_MANY)
            return this.config.sqlTypesEquivalenceJavascriptTypes.manyToMany;
        if (this.type === types_1.SqlType.RELATIONSHIP)
            return `${this.relationshipAggregate}[]`;
        return this.config.sqlTypesEquivalenceJavascriptTypes[this.type];
    }
    get getJavascriptModelType() {
        if (this.relationship === types_1.SqlRelationship.MANY_TO_MANY)
            return this.config.sqlTypesEquivalenceJavascriptTypes.manyToMany;
        if (this.type === types_1.SqlType.RELATIONSHIP)
            return `${this.relationshipAggregate}[]`;
        return this.config.sqlTypesEquivalenceJavascriptModelTypes[this.type];
    }
    get getSequelizeType() {
        let parameter;
        if (this.type === types_1.SqlType.CHAR)
            parameter = this.length; // parameter = length
        if (this.type === types_1.SqlType.VARCHAR)
            parameter = this.maxLength; // parameter = maxLength
        if (this.type === types_1.SqlType.ENUM)
            parameter = this.enumOptionsArrayItems; // parameter = values
        if (this.type === types_1.SqlType.DECIMAL)
            parameter = this.decimals; // parameter = decimals
        return cliter_config_1.cliterConfig.sqlTypesEquivalenceSequelizeTypes[this.type](parameter);
    }
    /********
     * REST *
     ********/
    get getSwaggerType() {
        return this.config.sqlTypesEquivalenceSwaggerTypes[this.type];
    }
    get getDtoType() {
        return this.config.sqlTypesEquivalenceDtoTypes[this.type];
    }
    /***********
     * GraphQL *
     ***********/
    get getGraphqlType() {
        if (this.relationship === types_1.SqlRelationship.ONE_TO_MANY || this.relationship === types_1.SqlRelationship.MANY_TO_MANY)
            return `[${this.relationshipAggregate}]`;
        if (this.relationship === types_1.SqlRelationship.MANY_TO_ONE)
            return `${this.relationshipAggregate}`;
        if (this.relationship === types_1.SqlRelationship.ONE_TO_ONE)
            return `${this.relationshipAggregate}`;
        return this.config.sqlTypesEquivalenceQraphqlTypes[this.type];
    }
    get getGraphqlCreateType() {
        var _a, _b;
        if (this.relationship === types_1.SqlRelationship.MANY_TO_MANY)
            return this.config.sqlTypesEquivalenceQraphqlTypes.manyToMany;
        if (this.relationship === types_1.SqlRelationship.ONE_TO_ONE && !this.relationshipField)
            return `${(_a = this.getRelationshipBoundedContext) === null || _a === void 0 ? void 0 : _a.toPascalCase()}Create${(_b = this.getRelationshipModule) === null || _b === void 0 ? void 0 : _b.toPascalCase()}Input`;
        return this.config.sqlTypesEquivalenceQraphqlTypes[this.type];
    }
    get getGraphqlUpdateType() {
        var _a, _b;
        if (this.relationship === types_1.SqlRelationship.MANY_TO_MANY)
            return this.config.sqlTypesEquivalenceQraphqlTypes.manyToMany;
        if (this.relationship === types_1.SqlRelationship.ONE_TO_ONE && !this.relationshipField)
            return `${(_a = this.getRelationshipBoundedContext) === null || _a === void 0 ? void 0 : _a.toPascalCase()}Update${(_b = this.getRelationshipModule) === null || _b === void 0 ? void 0 : _b.toPascalCase()}Input`;
        return this.config.sqlTypesEquivalenceQraphqlTypes[this.type];
    }
    /*************
     * DASHBOARD *
     *************/
    get getColumnDataType() {
        return this.config.sqlTypesEquivalenceDashboardColumnDataTypes[this.type];
    }
    /*****************
     * Miscellaneous *
     *****************/
    get hasQuotation() {
        return this.config.quotationTypes[this.type];
    }
    parseModuleSection(moduleSectionString) {
        const [boundedContextName, moduleName] = moduleSectionString.split('/');
        if (!boundedContextName || !moduleName)
            throw new Error('Must input bounded context and module name, with format: bounded-context/module');
        return yaml_manager_1.YamlManager.loadYamlConfigFile(boundedContextName, moduleName);
    }
    toDto() {
        return {
            id: this.id,
            name: this._name,
            type: this.type,
            primaryKey: this.primaryKey,
            autoIncrement: this.autoIncrement,
            enumOptions: this.enumOptions,
            decimals: this.decimals,
            length: this.length,
            minLength: this.minLength,
            maxLength: this.maxLength,
            nullable: this.nullable,
            defaultValue: this.defaultValue,
            relationship: this.relationship,
            relationshipSingularName: this.relationshipSingularName,
            relationshipAggregate: this.relationshipAggregate,
            relationshipModulePath: this.relationshipModulePath,
            relationshipKey: this.relationshipKey,
            relationshipField: this.relationshipField,
            relationshipAvoidConstraint: this.relationshipAvoidConstraint,
            relationshipPackageName: this.relationshipPackageName,
            pivotAggregateName: this.pivotAggregateName,
            pivotPath: this.pivotPath,
            pivotFileName: this.pivotFileName,
            isDenormalized: this.isDenormalized,
            index: this.index,
            indexName: this.indexName,
            isI18n: this.isI18n,
            example: this.example,
            faker: this.faker,
        };
    }
}
exports.Property = Property;
