"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.ManifestPersistence = void 0;
const internal_1 = require("../../internal");
const copyDataUtils = require("../../Utilities/CopyDataUtils");
const timeUtils = require("../../Utilities/timeUtils");
const AttributeGroupPersistence_1 = require("./AttributeGroupPersistence");
const ConstantEntityPersistence_1 = require("./ConstantEntityPersistence");
const DataTypePersistence_1 = require("./DataTypePersistence");
const DocumentPersistence_1 = require("./DocumentPersistence");
const E2ERelationshipPersistence_1 = require("./E2ERelationshipPersistence");
const EntityPersistence_1 = require("./EntityPersistence");
const ImportPersistence_1 = require("./ImportPersistence");
const LocalEntityDeclarationPersistence_1 = require("./LocalEntityDeclarationPersistence");
const ManifestDeclarationPersistence_1 = require("./ManifestDeclarationPersistence");
const PurposePersistence_1 = require("./PurposePersistence");
const ReferencedEntityDeclarationPersistence_1 = require("./ReferencedEntityDeclarationPersistence");
const TraitPersistence_1 = require("./TraitPersistence");
const types_1 = require("./types");
const utils = require("./utils");
class ManifestPersistence {
    static fromObject(ctx, name, namespace, path, dataObj) {
        // Determine name of the manifest
        let manifestName;
        if (dataObj) {
            manifestName = !internal_1.StringUtils.isBlankByCdmStandard(dataObj.manifestName) ? dataObj.manifestName : dataObj.folioName;
        }
        // We haven't found the name in the file, use one provided in the call but without the suffixes
        if (!manifestName && name) {
            manifestName = name.replace(internal_1.CdmConstants.manifestExtension, '')
                .replace(internal_1.CdmConstants.folioExtension, '');
        }
        const manifest = ctx.corpus.MakeObject(internal_1.cdmObjectType.manifestDef, manifestName);
        // this is the document name which is assumed by constructor to be related to the the manifestName, but may not be
        manifest.name = name;
        manifest.folderPath = path;
        manifest.namespace = namespace;
        if (dataObj) {
            if (dataObj.explanation) {
                manifest.explanation = dataObj.explanation;
            }
            if (!internal_1.StringUtils.isBlankByCdmStandard(dataObj.$schema)) {
                manifest.schema = dataObj.$schema;
            }
            // support old model syntax
            if (!internal_1.StringUtils.isBlankByCdmStandard(dataObj.schemaVersion)) {
                manifest.jsonSchemaSemanticVersion = dataObj.schemaVersion;
            }
            if (!internal_1.StringUtils.isBlankByCdmStandard(dataObj.jsonSchemaSemanticVersion)) {
                manifest.jsonSchemaSemanticVersion = dataObj.jsonSchemaSemanticVersion;
            }
            if (manifest.jsonSchemaSemanticVersion !== '1.0.0') {
                // tslint:disable-next-line:no-suspicious-comment
                // TODO: validate that this is a version we can understand with the OM
            }
            if (!internal_1.StringUtils.isBlankByCdmStandard(dataObj.documentVersion)) {
                manifest.documentVersion = dataObj.documentVersion;
            }
            if (!internal_1.StringUtils.isBlankByCdmStandard(dataObj.manifestName)) {
                manifest.manifestName = dataObj.manifestName;
                // Might be populated in the case of folio.cdm.json or manifest.cdm.json file.
            }
            else if (!internal_1.StringUtils.isBlankByCdmStandard(dataObj.folioName)) {
                manifest.manifestName = dataObj.folioName;
            }
            if (dataObj.imports) {
                for (const importObj of dataObj.imports) {
                    manifest.imports.push(ImportPersistence_1.ImportPersistence.fromData(ctx, importObj));
                }
            }
            if (dataObj.definitions && Array.isArray(dataObj.definitions)) {
                for (const definition of dataObj.definitions) {
                    if ('dataTypeName' in definition) {
                        manifest.definitions.push(DataTypePersistence_1.DataTypePersistence.fromData(ctx, definition));
                    }
                    else if ('purposeName' in definition) {
                        manifest.definitions.push(PurposePersistence_1.PurposePersistence.fromData(ctx, definition));
                    }
                    else if ('attributeGroupName' in definition) {
                        manifest.definitions.push(AttributeGroupPersistence_1.AttributeGroupPersistence.fromData(ctx, definition));
                    }
                    else if ('traitName' in definition) {
                        manifest.definitions.push(TraitPersistence_1.TraitPersistence.fromData(ctx, definition));
                    }
                    else if ('entityShape' in definition) {
                        manifest.definitions.push(ConstantEntityPersistence_1.ConstantEntityPersistence.fromData(ctx, definition));
                    }
                    else if ('entityName' in definition) {
                        manifest.definitions.push(EntityPersistence_1.EntityPersistence.fromData(ctx, definition));
                    }
                }
            }
            if (dataObj.lastFileStatusCheckTime) {
                manifest.lastFileStatusCheckTime = new Date(dataObj.lastFileStatusCheckTime);
            }
            if (dataObj.lastFileModifiedTime) {
                manifest.lastFileModifiedTime = new Date(dataObj.lastFileModifiedTime);
            }
            if (dataObj.lastChildFileModifiedTime) {
                manifest.lastChildFileModifiedTime = new Date(dataObj.lastChildFileModifiedTime);
            }
            utils.addArrayToCdmCollection(manifest.exhibitsTraits, utils.createTraitReferenceArray(ctx, dataObj.exhibitsTraits));
            if (dataObj.entities) {
                const fullPath = `${!internal_1.StringUtils.isBlankByCdmStandard(namespace) ? `${namespace}:${path}` : path}`;
                for (const entityObj of dataObj.entities) {
                    let entity;
                    if (entityObj.type) {
                        if (entityObj.type === types_1.entityDeclarationDefinitionType.localEntity) {
                            entity = LocalEntityDeclarationPersistence_1.LocalEntityDeclarationPersistence.fromData(ctx, fullPath, entityObj);
                        }
                        else if (entityObj.type === types_1.entityDeclarationDefinitionType.referencedEntity) {
                            entity = ReferencedEntityDeclarationPersistence_1.ReferencedEntityDeclarationPersistence.fromData(ctx, fullPath, entityObj);
                        }
                        else {
                            internal_1.Logger.error(ctx, this.TAG, this.fromObject.name, undefined, internal_1.cdmLogCode.ErrPersistEntityDeclarationMissing, entityObj.entityName);
                        }
                    }
                    else {
                        // We see old structure of entity declaration, check for entity schema/declaration.
                        if (entityObj.entitySchema) {
                            // Local entity declaration used to use entity schema.
                            entity = LocalEntityDeclarationPersistence_1.LocalEntityDeclarationPersistence.fromData(ctx, fullPath, entityObj);
                        }
                        else {
                            // While referenced entity declaration used to use entity declaration.
                            entity = ReferencedEntityDeclarationPersistence_1.ReferencedEntityDeclarationPersistence.fromData(ctx, fullPath, entityObj);
                        }
                    }
                    manifest.entities.push(entity);
                }
                // Checks if incremental trait is needed from foundations.cdm.json
                this.importFoundationsIfIncrementalPartitionTraitExist(manifest);
            }
            if (dataObj.relationships) {
                for (const rel of dataObj.relationships) {
                    manifest.relationships.push(E2ERelationshipPersistence_1.E2ERelationshipPersistence.fromData(ctx, rel));
                }
            }
            if (dataObj.subManifests) {
                for (const subManifest of dataObj.subManifests) {
                    manifest.subManifests.push(ManifestDeclarationPersistence_1.ManifestDeclarationPersistence.fromData(ctx, subManifest));
                }
                // Might be populated in the case of folio.cdm.json or manifest.cdm.json file.
            }
            else if (dataObj.subFolios) {
                for (const subFolio of dataObj.subFolios) {
                    manifest.subManifests.push(ManifestDeclarationPersistence_1.ManifestDeclarationPersistence.fromData(ctx, subFolio));
                }
            }
        }
        return manifest;
    }
    static fromData(ctx, docName, jsonData, folder) {
        const dataObj = JSON.parse(jsonData);
        return ManifestPersistence.fromObject(ctx, docName, folder.namespace, folder.folderPath, dataObj);
    }
    static toData(instance, resOpt, options) {
        // Checks if incremental trait is needed from foundations.cdm.json
        this.importFoundationsIfIncrementalPartitionTraitExist(instance);
        const manifestContent = DocumentPersistence_1.DocumentPersistence.toData(instance, resOpt, options);
        manifestContent.manifestName = instance.manifestName;
        manifestContent.lastFileStatusCheckTime = timeUtils.getFormattedDateString(instance.lastFileStatusCheckTime);
        manifestContent.lastFileModifiedTime = timeUtils.getFormattedDateString(instance.lastFileModifiedTime);
        manifestContent.lastChildFileModifiedTime = timeUtils.getFormattedDateString(instance.lastChildFileModifiedTime);
        manifestContent.documentVersion = instance.documentVersion;
        manifestContent.explanation = instance.explanation;
        manifestContent.exhibitsTraits = copyDataUtils.arrayCopyData(resOpt, instance.exhibitsTraits.allItems, options);
        manifestContent.entities = copyDataUtils.arrayCopyData(resOpt, instance.entities, options);
        manifestContent.subManifests = copyDataUtils.arrayCopyData(resOpt, instance.subManifests, options);
        if (instance.imports && instance.imports.length > 0) {
            manifestContent.imports = [];
            instance.imports.allItems.forEach((importDoc) => {
                manifestContent.imports.push(ImportPersistence_1.ImportPersistence.toData(importDoc, new internal_1.resolveOptions(), {}));
            });
        }
        if (instance.relationships && instance.relationships.length > 0) {
            manifestContent.relationships = instance.relationships.allItems.map((relationship) => {
                return E2ERelationshipPersistence_1.E2ERelationshipPersistence.toData(relationship, resOpt, options);
            });
        }
        return manifestContent;
    }
    /**
     *
     * Checks if incremental trait is needed from foundations.cdm.json
     */
    static importFoundationsIfIncrementalPartitionTraitExist(manifest) {
        var _a, _b;
        if (manifest.entities == null) {
            return;
        }
        for (const ent of manifest.entities) {
            if ((0, internal_1.isLocalEntityDeclarationDefinition)(ent)) {
                if (((_a = ent.incrementalPartitions) === null || _a === void 0 ? void 0 : _a.length) > 0 || ((_b = ent.incrementalPartitionPatterns) === null || _b === void 0 ? void 0 : _b.length) > 0) {
                    if (manifest.imports.item(internal_1.constants.FOUNDATIONS_CORPUS_PATH, undefined, false) === undefined) {
                        manifest.imports.push(internal_1.constants.FOUNDATIONS_CORPUS_PATH);
                        // Find one is enough
                        break;
                    }
                }
            }
        }
    }
}
exports.ManifestPersistence = ManifestPersistence;
ManifestPersistence.TAG = ManifestPersistence.name;
// Whether this persistence class has async methods.
ManifestPersistence.isPersistenceAsync = false;
// The file format/extension types this persistence class supports.
ManifestPersistence.formats = [internal_1.CdmConstants.manifestExtension, internal_1.CdmConstants.folioExtension];
//# sourceMappingURL=ManifestPersistence.js.map