"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const dynamo_easy_config_1 = require("../../../config/dynamo-easy-config");
const moment_type_1 = require("../../../mapper/type/moment.type");
const util_1 = require("../../../mapper/util");
const util_2 = require("../../util");
const index_type_enum_1 = require("../index/index-type.enum");
exports.KEY_PROPERTY = 'sc-reflect:property';
function Property(opts = {}) {
    return (target, propertyKey) => {
        if (typeof propertyKey === 'string') {
            const propertyOptions = {
                name: propertyKey,
                nameDb: opts.name || propertyKey,
            };
            initOrUpdateProperty(propertyOptions, target, propertyKey);
        }
    };
}
exports.Property = Property;
function initOrUpdateIndex(indexType, indexData, target, propertyKey) {
    const properties = Reflect.getMetadata(exports.KEY_PROPERTY, target.constructor) || [];
    const existingProperty = properties.find(property => property.name === propertyKey);
    let propertyMetadata;
    switch (indexType) {
        case index_type_enum_1.IndexType.GSI:
            propertyMetadata = initOrUpdateGSI(existingProperty && existingProperty.keyForGSI ? existingProperty.keyForGSI : {}, indexData);
            break;
        case index_type_enum_1.IndexType.LSI:
            propertyMetadata = initOrUpdateLSI(existingProperty && existingProperty.sortKeyForLSI ? existingProperty.sortKeyForLSI : [], indexData);
            break;
        default:
            throw new Error(`unsupported index type ${indexType}`);
    }
    initOrUpdateProperty(propertyMetadata, target, propertyKey);
}
exports.initOrUpdateIndex = initOrUpdateIndex;
function initOrUpdateGSI(indexes, indexData) {
    if (indexes[indexData.name]) {
        // TODO LOW:INVESTIGATE when we throw an error we have a problem where multiple different classes extend one base class, this will be executed by multiple times
        // throw new Error(
        //   'the property with name is already registered as key for index - one property can only define one key per index'
        // )
    }
    else {
        indexes[indexData.name] = indexData.keyType;
    }
    return { keyForGSI: indexes };
}
function initOrUpdateLSI(indexes, indexData) {
    indexes.push(indexData.name);
    return { sortKeyForLSI: indexes };
}
function initOrUpdateProperty(propertyMetadata = {}, target, propertyKey) {
    // Update the attribute array
    const properties = Reflect.getMetadata(exports.KEY_PROPERTY, target.constructor) || [];
    const existingProperty = properties.find(property => property.name === propertyKey);
    if (existingProperty) {
        // merge property options
        // console.log('merge into existing property', existingProperty, propertyMetadata);
        Object.assign(existingProperty, propertyMetadata);
    }
    else {
        // add new options
        const newProperty = createNewProperty(propertyMetadata, target, propertyKey);
        // console.log('new property', newProperty);
        properties.push(newProperty);
    }
    Reflect.defineMetadata(exports.KEY_PROPERTY, properties, target.constructor);
}
exports.initOrUpdateProperty = initOrUpdateProperty;
function createNewProperty(propertyOptions = {}, target, propertyKey) {
    let propertyType = util_2.getMetadataType(target, propertyKey);
    let customType = isCustomType(propertyType);
    const typeByConvention = util_1.Util.typeByConvention(propertyKey);
    if (typeByConvention) {
        customType = true;
        if (dynamo_easy_config_1.DynamoEasyConfig.config) {
            switch (typeByConvention) {
                case 'date':
                    switch (dynamo_easy_config_1.DynamoEasyConfig.config.dateType) {
                        case 'default':
                            propertyType = Date;
                            break;
                        case 'moment':
                            propertyType = moment_type_1.MomentType;
                            break;
                        default:
                            throw new Error(`Unsupported date type on model metadata <${dynamo_easy_config_1.DynamoEasyConfig.config.dateType}>`);
                    }
                    break;
            }
        }
    }
    const typeInfo = {
        type: propertyType,
        isCustom: customType,
    };
    // console.log(`#### propertyKey: ${propertyKey} / typeInfo: ${JSON.stringify(typeInfo)}`);
    propertyOptions = Object.assign({ name: propertyKey, nameDb: propertyKey, typeInfo }, propertyOptions);
    return propertyOptions;
}
/**
 * TODO LOW:BINARY make sure to implement the context dependant details of Binary (Buffer vs. Uint8Array)
 * @returns {boolean} true if the type cannot be mapped by dynamo document client
 */
function isCustomType(type) {
    return type !== String && type !== Number && type !== Boolean && type !== Uint8Array;
}
//# sourceMappingURL=property.decorator.js.map