"use strict";
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.processTraitsAndAnnotationsToData = exports.processAnnotationsFromData = exports.createCsvFormatSettings = exports.createCsvTrait = exports.shouldPersistTrait = exports.convertTraitToAnnotation = exports.convertAnnotationToTrait = exports.shouldAnnotationGoIntoASingleTrait = exports.partitionSettingsSupportedArguments = exports.modelJsonPropertyTraits = exports.ignoredTraits = void 0;
const __1 = require("..");
const internal_1 = require("../../internal");
const ExtensionHelper_1 = require("./ExtensionHelper");
const types_1 = require("./types");
const NameValuePair_1 = require("../../Utilities/NameValuePair");
const ArgumentPersistence_1 = require("./ArgumentPersistence");
const annotationToTraitMap = new Map([['version', 'is.CDM.entityVersion']]);
const traitToAnnotationMap = new Map([['is.CDM.entityVersion', 'version']]);
exports.ignoredTraits = new Set().add('is.modelConversion.otherAnnotations')
    .add('is.propertyContent.multiTrait')
    .add('is.modelConversion.referenceModelMap')
    .add('is.modelConversion.modelVersion')
    .add('means.measurement.version')
    .add('is.CDM.entityVersion')
    .add('is.partition.culture')
    .add('is.managedBy')
    .add('is.hidden');
// Traits to ignore if they come from properties.
// These traits become properties on the model.json. To avoid persisting both a trait
// and a property on the model.json, we filter these traits out.
exports.modelJsonPropertyTraits = new Set().add('is.localized.describedAs');
// Arguments natively supported by the fileFormatSettings property.
exports.partitionSettingsSupportedArguments = new Set()
    .add('columnHeaders')
    .add('csvStyle')
    .add('delimiter')
    .add('quoteStyle')
    .add('encoding');
function shouldAnnotationGoIntoASingleTrait(name) {
    return annotationToTraitMap.has(name);
}
exports.shouldAnnotationGoIntoASingleTrait = shouldAnnotationGoIntoASingleTrait;
function convertAnnotationToTrait(name) {
    return annotationToTraitMap.get(name);
}
exports.convertAnnotationToTrait = convertAnnotationToTrait;
function convertTraitToAnnotation(name) {
    return traitToAnnotationMap.get(name);
}
exports.convertTraitToAnnotation = convertTraitToAnnotation;
function shouldPersistTrait(traitBase) {
    if (!(traitBase instanceof internal_1.CdmTraitReference)) {
        return true;
    }
    const trait = traitBase;
    switch (trait.namedReference) {
        case "is.partition.format.CSV":
            var argumentNames = trait.arguments.allItems.filter(arg => !!arg.name).map(arg => arg.name);
            // Checks if the trait contains arguments that are not supported natively by the model.json CsvFormatSettings property.
            return argumentNames.filter(argName => !exports.partitionSettingsSupportedArguments.has(argName)).length > 0;
        default:
            return true;
    }
}
exports.shouldPersistTrait = shouldPersistTrait;
function createCsvTrait(object, ctx, host) {
    const csvFormatTrait = host !== null && host !== void 0 ? host : ctx.corpus.MakeObject(internal_1.cdmObjectType.traitRef, 'is.partition.format.CSV', false);
    var argumentNames = new Set(csvFormatTrait.arguments.allItems.filter(arg => !arg.name).map(arg => arg.name));
    if (object.columnHeaders !== undefined && !argumentNames.has('columnHeaders')) {
        const columnHeadersArg = ctx.corpus.MakeObject(internal_1.cdmObjectType.argumentDef, 'columnHeaders');
        columnHeadersArg.value = object.columnHeaders === 'true' || object.columnHeaders === true ? 'true' : 'false';
        csvFormatTrait.arguments.push(columnHeadersArg);
    }
    if (object.csvStyle !== undefined && !argumentNames.has('csvStyle')) {
        const csvStyleArg = ctx.corpus.MakeObject(internal_1.cdmObjectType.argumentDef, 'csvStyle');
        csvStyleArg.value = object.csvStyle;
        csvFormatTrait.arguments.push(csvStyleArg);
    }
    if (object.delimiter !== undefined && !argumentNames.has('delimiter')) {
        const delimiterArg = ctx.corpus.MakeObject(internal_1.cdmObjectType.argumentDef, 'delimiter');
        delimiterArg.value = object.delimiter;
        csvFormatTrait.arguments.push(delimiterArg);
    }
    if (object.quoteStyle !== undefined && !argumentNames.has('quoteStyle')) {
        const quoteStyleArg = ctx.corpus.MakeObject(internal_1.cdmObjectType.argumentDef, 'quoteStyle');
        quoteStyleArg.value = object.quoteStyle;
        csvFormatTrait.arguments.push(quoteStyleArg);
    }
    if (object.encoding !== undefined && !argumentNames.has('encoding')) {
        const encodingArg = ctx.corpus.MakeObject(internal_1.cdmObjectType.argumentDef, 'encoding');
        encodingArg.value = object.encoding;
        csvFormatTrait.arguments.push(encodingArg);
    }
    return csvFormatTrait;
}
exports.createCsvTrait = createCsvTrait;
function createCsvFormatSettings(csvFormatTrait) {
    const result = {};
    for (const argument of csvFormatTrait.arguments.allItems) {
        if (argument.name === 'columnHeaders') {
            result.columnHeaders = argument.value === 'true';
        }
        if (argument.name === 'csvStyle') {
            result.csvStyle = argument.value;
        }
        if (argument.name === 'delimiter') {
            result.delimiter = argument.value;
        }
        if (argument.name === 'quoteStyle') {
            result.quoteStyle = argument.value;
        }
        if (argument.name === 'encoding') {
            result.encoding = argument.value;
        }
    }
    return result;
}
exports.createCsvFormatSettings = createCsvFormatSettings;
function processAnnotationsFromData(ctx, object, traits) {
    return __awaiter(this, void 0, void 0, function* () {
        const multiTraitAnnotations = [];
        if (object.annotations !== undefined) {
            for (const annotation of object.annotations) {
                if (!shouldAnnotationGoIntoASingleTrait(annotation.name)) {
                    const cdmElement = new NameValuePair_1.NameValuePair();
                    cdmElement.name = annotation.name;
                    cdmElement.value = annotation.value;
                    multiTraitAnnotations.push(cdmElement);
                }
                else {
                    const innerTrait = ctx.corpus.MakeObject(internal_1.cdmObjectType.traitRef, convertAnnotationToTrait(annotation.name));
                    innerTrait.arguments.push(yield __1.ModelJson.ArgumentPersistence.fromData(ctx, annotation));
                    traits.push(innerTrait);
                }
            }
            if (multiTraitAnnotations.length > 0) {
                const trait = ctx.corpus.MakeObject(internal_1.cdmObjectType.traitRef, 'is.modelConversion.otherAnnotations', false);
                trait.isFromProperty = false;
                const annotationsArguemnt = new internal_1.CdmArgumentDefinition(ctx, 'annotations');
                annotationsArguemnt.value = multiTraitAnnotations;
                trait.arguments.push(annotationsArguemnt);
                traits.push(trait);
            }
        }
        if (object['cdm:traits'] !== undefined) {
            object['cdm:traits'].forEach((trait) => {
                if (typeof trait !== 'string' && 'traitGroupReference' in trait) {
                    traits.push(__1.CdmFolder.TraitGroupReferencePersistence.fromData(ctx, trait));
                }
                else {
                    traits.push(__1.CdmFolder.TraitReferencePersistence.fromData(ctx, trait));
                }
            });
        }
    });
}
exports.processAnnotationsFromData = processAnnotationsFromData;
function processTraitsAndAnnotationsToData(ctx, entityObject, traits) {
    return __awaiter(this, void 0, void 0, function* () {
        if (traits === undefined) {
            return;
        }
        const annotations = [];
        const extensions = [];
        for (const trait of traits) {
            if (ExtensionHelper_1.traitRefIsExtension(trait)) {
                // Safe to cast since extensions can only be trait refs, not trait group refs
                ExtensionHelper_1.processExtensionTraitToObject(trait, entityObject);
            }
            else if (trait.namedReference === 'is.modelConversion.otherAnnotations') {
                // Safe to cast since extensions can only be trait refs, not trait group refs
                for (const annotation of trait.arguments.allItems[0].value) {
                    if (annotation instanceof NameValuePair_1.NameValuePair) {
                        const element = new types_1.Annotation();
                        element.name = annotation.name;
                        element.value = annotation.value;
                        annotations.push(element);
                    }
                    else if (typeof annotation === 'object') {
                        annotations.push(annotation);
                    }
                    else {
                        internal_1.Logger.warning(ctx, this.TAG, this.processTraitsAndAnnotationsToData.name, trait.atCorpusPath, internal_1.cdmLogCode.WarnAnnotationTypeNotSupported);
                    }
                }
            }
            else if (internal_1.isCdmTraitReference(trait) && traitToAnnotationMap.has(trait.namedReference)) {
                const element = yield ArgumentPersistence_1.ArgumentPersistence.toData(trait.arguments.allItems[0], undefined, undefined);
                element.name = convertTraitToAnnotation(trait.namedReference);
                annotations.push(element);
            }
            else if (!exports.ignoredTraits.has(trait.namedReference)
                && !trait.namedReference.startsWith('is.dataFormat')
                && !(exports.modelJsonPropertyTraits.has(trait.namedReference) && trait instanceof internal_1.CdmTraitReference && trait.isFromProperty)
                && shouldPersistTrait(trait)) {
                if (trait instanceof internal_1.CdmTraitGroupReference) {
                    extensions.push(__1.CdmFolder.TraitGroupReferencePersistence.toData(trait, undefined, undefined));
                }
                else {
                    extensions.push(__1.CdmFolder.TraitReferencePersistence.toData(trait, undefined, undefined));
                }
            }
            if (annotations.length > 0) {
                entityObject.annotations = annotations;
            }
            if (extensions.length > 0) {
                entityObject['cdm:traits'] = extensions;
            }
        }
    });
}
exports.processTraitsAndAnnotationsToData = processTraitsAndAnnotationsToData;
//# sourceMappingURL=utils.js.map