"use strict";
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
Object.defineProperty(exports, "__esModule", { value: true });
exports.DocumentPersistence = void 0;
const __1 = require("..");
const internal_1 = require("../../internal");
const copyDataUtils = require("../../Utilities/CopyDataUtils");
class DocumentPersistence {
    static fromObject(ctx, name, namespace, path, object) {
        const document = ctx.corpus.MakeObject(internal_1.cdmObjectType.documentDef, name);
        document.folderPath = path;
        document.namespace = namespace;
        if (object) {
            if (object.$schema) {
                document.schema = object.$schema;
            }
            // support old model syntax
            if (object.schemaVersion) {
                document.jsonSchemaSemanticVersion = object.schemaVersion;
            }
            if (object.documentVersion) {
                document.documentVersion = object.documentVersion;
            }
            if (object.imports) {
                for (const importObj of object.imports) {
                    document.imports.push(__1.CdmFolder.ImportPersistence.fromData(ctx, importObj));
                }
            }
            if (object.definitions && Array.isArray(object.definitions)) {
                for (const definition of object.definitions) {
                    if ('dataTypeName' in definition) {
                        document.definitions.push(__1.CdmFolder.DataTypePersistence.fromData(ctx, definition));
                    }
                    else if ('purposeName' in definition) {
                        document.definitions.push(__1.CdmFolder.PurposePersistence.fromData(ctx, definition));
                    }
                    else if ('attributeGroupName' in definition) {
                        document.definitions.push(__1.CdmFolder.AttributeGroupPersistence.fromData(ctx, definition));
                    }
                    else if ('traitName' in definition) {
                        document.definitions.push(__1.CdmFolder.TraitPersistence.fromData(ctx, definition));
                    }
                    else if ('traitGroupName' in definition) {
                        document.definitions.push(__1.CdmFolder.TraitGroupPersistence.fromData(ctx, definition));
                    }
                    else if ('entityShape' in definition) {
                        document.definitions.push(__1.CdmFolder.ConstantEntityPersistence.fromData(ctx, definition));
                    }
                    else if ('entityName' in definition) {
                        document.definitions.push(__1.CdmFolder.EntityPersistence.fromData(ctx, definition));
                    }
                }
            }
        }
        let isResolvedDoc = false;
        if (document.definitions.length === 1 && document.definitions.allItems[0].objectType == internal_1.cdmObjectType.entityDef) {
            const entity = document.definitions.allItems[0];
            const resolvedTrait = entity.exhibitsTraits.item('has.entitySchemaAbstractionLevel');
            // Tries to figure out if the document is in resolved form by looking for the schema abstraction trait
            // or the presence of the attribute context.
            isResolvedDoc = resolvedTrait != null && resolvedTrait.arguments.allItems[0].value == 'resolved';
            isResolvedDoc = isResolvedDoc || !!entity.attributeContext;
        }
        if (object.jsonSchemaSemanticVersion) {
            document.jsonSchemaSemanticVersion = object.jsonSchemaSemanticVersion;
            if (DocumentPersistence.compareJsonSemanticVersion(ctx, document.jsonSchemaSemanticVersion) > 0) {
                if (isResolvedDoc) {
                    internal_1.Logger.warning(ctx, this.TAG, this.fromObject.name, null, internal_1.cdmLogCode.WarnPersistUnsupportedJsonSemVer, internal_1.CdmDocumentDefinition.currentJsonSchemaSemanticVersion, document.jsonSchemaSemanticVersion);
                }
                else {
                    internal_1.Logger.error(ctx, this.TAG, this.fromObject.name, null, internal_1.cdmLogCode.ErrPersistUnsupportedJsonSemVer, internal_1.CdmDocumentDefinition.currentJsonSchemaSemanticVersion, document.jsonSchemaSemanticVersion);
                }
            }
        }
        else {
            internal_1.Logger.warning(ctx, this.TAG, this.fromObject.name, null, internal_1.cdmLogCode.WarnPersistJsonSemVerMandatory);
        }
        return document;
    }
    static fromData(ctx, docName, jsonData, folder) {
        const obj = JSON.parse(jsonData);
        return DocumentPersistence.fromObject(ctx, docName, folder.namespace, folder.folderPath, obj);
    }
    static toData(instance, resOpt, options) {
        return {
            $schema: instance.schema,
            jsonSchemaSemanticVersion: instance.jsonSchemaSemanticVersion,
            imports: copyDataUtils.arrayCopyData(resOpt, instance.imports, options),
            definitions: copyDataUtils.arrayCopyData(resOpt, instance.definitions, options),
            documentVersion: instance.documentVersion
        };
    }
    /**
     * Compares the document version with the json semantic version supported.
     * 1 => if documentSemanticVersion > jsonSemanticVersion
     * 0 => if documentSemanticVersion == jsonSemanticVersion or if documentSemanticVersion is invalid
     * -1 => if documentSemanticVersion < jsonSemanticVersion
     */
    static compareJsonSemanticVersion(ctx, documentSemanticVersion) {
        const docSemanticVersionSplit = documentSemanticVersion.split(".").map(x => Number(x));
        const currSemanticVersionSplit = internal_1.CdmDocumentDefinition.currentJsonSchemaSemanticVersion.split(".").map(x => Number(x));
        if (docSemanticVersionSplit.length !== 3 || docSemanticVersionSplit.includes(NaN)) {
            internal_1.Logger.warning(ctx, this.TAG, this.compareJsonSemanticVersion.name, null, internal_1.cdmLogCode.WarnPersistJsonSemVerInvalidFormat);
            return 0;
        }
        for (let i = 0; i < 3; ++i) {
            if (docSemanticVersionSplit[i] !== currSemanticVersionSplit[i]) {
                return docSemanticVersionSplit[i] < currSemanticVersionSplit[i] ? -1 : 1;
            }
        }
        return 0;
    }
}
exports.DocumentPersistence = DocumentPersistence;
DocumentPersistence.TAG = DocumentPersistence.name;
/**
 * Whether this persistence class has async methods.
 */
DocumentPersistence.isPersistenceAsync = false;
/**
 * The file format/extension types this persistence class supports.
 */
DocumentPersistence.formats = [internal_1.CdmConstants.cdmExtension];
//# sourceMappingURL=DocumentPersistence.js.map