import * as tslib_1 from "tslib";
import { DynamoEasyConfig } from '../../../config/dynamo-easy-config';
import { MomentType } from '../../../mapper/type/moment.type';
import { Util } from '../../../mapper/util';
import { getMetadataType } from '../../util';
import { IndexType } from '../index/index-type.enum';
export var KEY_PROPERTY = 'sc-reflect:property';
export function Property(opts) {
    if (opts === void 0) { opts = {}; }
    return function (target, propertyKey) {
        if (typeof propertyKey === 'string') {
            var propertyOptions = {
                name: propertyKey,
                nameDb: opts.name || propertyKey,
            };
            initOrUpdateProperty(propertyOptions, target, propertyKey);
        }
    };
}
export function initOrUpdateIndex(indexType, indexData, target, propertyKey) {
    var properties = Reflect.getMetadata(KEY_PROPERTY, target.constructor) || [];
    var existingProperty = properties.find(function (property) { return property.name === propertyKey; });
    var propertyMetadata;
    switch (indexType) {
        case IndexType.GSI:
            propertyMetadata = initOrUpdateGSI(existingProperty && existingProperty.keyForGSI ? existingProperty.keyForGSI : {}, indexData);
            break;
        case IndexType.LSI:
            propertyMetadata = initOrUpdateLSI(existingProperty && existingProperty.sortKeyForLSI ? existingProperty.sortKeyForLSI : [], indexData);
            break;
        default:
            throw new Error("unsupported index type " + indexType);
    }
    initOrUpdateProperty(propertyMetadata, target, propertyKey);
}
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 };
}
export function initOrUpdateProperty(propertyMetadata, target, propertyKey) {
    // Update the attribute array
    if (propertyMetadata === void 0) { propertyMetadata = {}; }
    var properties = Reflect.getMetadata(KEY_PROPERTY, target.constructor) || [];
    var existingProperty = properties.find(function (property) { return property.name === propertyKey; });
    if (existingProperty) {
        // merge property options
        // console.log('merge into existing property', existingProperty, propertyMetadata);
        Object.assign(existingProperty, propertyMetadata);
    }
    else {
        // add new options
        var newProperty = createNewProperty(propertyMetadata, target, propertyKey);
        // console.log('new property', newProperty);
        properties.push(newProperty);
    }
    Reflect.defineMetadata(KEY_PROPERTY, properties, target.constructor);
}
function createNewProperty(propertyOptions, target, propertyKey) {
    if (propertyOptions === void 0) { propertyOptions = {}; }
    var propertyType = getMetadataType(target, propertyKey);
    var customType = isCustomType(propertyType);
    var typeByConvention = Util.typeByConvention(propertyKey);
    if (typeByConvention) {
        customType = true;
        if (DynamoEasyConfig.config) {
            switch (typeByConvention) {
                case 'date':
                    switch (DynamoEasyConfig.config.dateType) {
                        case 'default':
                            propertyType = Date;
                            break;
                        case 'moment':
                            propertyType = MomentType;
                            break;
                        default:
                            throw new Error("Unsupported date type on model metadata <" + DynamoEasyConfig.config.dateType + ">");
                    }
                    break;
            }
        }
    }
    var typeInfo = {
        type: propertyType,
        isCustom: customType,
    };
    // console.log(`#### propertyKey: ${propertyKey} / typeInfo: ${JSON.stringify(typeInfo)}`);
    propertyOptions = tslib_1.__assign({ name: propertyKey, nameDb: propertyKey, typeInfo: 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