"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.CdmLocalEntityDeclarationDefinition = void 0;
const internal_1 = require("../internal");
const timeUtils = require("../Utilities/timeUtils");
const StringUtils_1 = require("../Utilities/StringUtils");
/**
 * The object model implementation for local entity declaration.
 */
class CdmLocalEntityDeclarationDefinition extends internal_1.CdmObjectDefinitionBase {
    /**
     * Initializes a new instance of the LocalEntityDeclarationImpl.
     * @param ctx The context.
     * @param entityName The entity name.
     */
    constructor(ctx, entityName) {
        super(ctx);
        this.TAG = CdmLocalEntityDeclarationDefinition.name;
        this.objectType = internal_1.cdmObjectType.localEntityDeclarationDef;
        this.entityName = entityName;
        this.dataPartitions = new internal_1.CdmCollection(this.ctx, this, internal_1.cdmObjectType.dataPartitionDef);
        this.dataPartitionPatterns = new internal_1.CdmCollection(this.ctx, this, internal_1.cdmObjectType.dataPartitionDef);
        this.incrementalPartitions = new internal_1.CdmCollection(this.ctx, this, internal_1.cdmObjectType.dataPartitionDef);
        this.incrementalPartitionPatterns = new internal_1.CdmCollection(this.ctx, this, internal_1.cdmObjectType.dataPartitionDef);
        this.lastFileModifiedTime = null;
        this.lastFileModifiedOldTime = null;
    }
    static get objectType() {
        return internal_1.cdmObjectType.localEntityDeclarationDef;
    }
    /**
     * @inheritdoc
     */
    getObjectType() {
        return internal_1.cdmObjectType.localEntityDeclarationDef;
    }
    /**
     * @inheritdoc
     */
    validate() {
        if (!this.entityName) {
            let missingFields = ['entityName'];
            internal_1.Logger.error(this.ctx, this.TAG, this.validate.name, this.atCorpusPath, internal_1.cdmLogCode.ErrValdnIntegrityCheckFailure, missingFields.map((s) => `'${s}'`).join(', '), this.atCorpusPath);
            return false;
        }
        return true;
    }
    /**
     * @inheritdoc
     */
    copy(resOpt, host) {
        if (!resOpt) {
            resOpt = new internal_1.resolveOptions(this, this.ctx.corpus.defaultResolutionDirectives);
        }
        let copy;
        if (!host) {
            copy = new CdmLocalEntityDeclarationDefinition(this.ctx, this.entityName);
        }
        else {
            copy = host;
            copy.entityName = this.entityName;
            copy.dataPartitionPatterns.clear();
            copy.dataPartitions.clear();
            copy.incrementalPartitionPatterns.clear();
            copy.incrementalPartitions.clear();
        }
        copy.entityPath = this.entityPath;
        copy.lastFileStatusCheckTime = this.lastFileStatusCheckTime;
        copy.lastFileModifiedTime = this.lastFileModifiedTime;
        copy.lastChildFileModifiedTime = this.lastChildFileModifiedTime;
        for (const partition of this.dataPartitions) {
            copy.dataPartitions.push(partition.copy(resOpt));
        }
        for (const pattern of this.dataPartitionPatterns) {
            copy.dataPartitionPatterns.push(pattern.copy(resOpt));
        }
        for (const partition of this.incrementalPartitions) {
            copy.incrementalPartitions.push(partition.copy(resOpt));
        }
        for (const pattern of this.incrementalPartitionPatterns) {
            copy.incrementalPartitionPatterns.push(pattern.copy(resOpt));
        }
        this.copyDef(resOpt, copy);
        return copy;
    }
    /**
     * @inheritdoc
     */
    getName() {
        return this.entityName;
    }
    /**
     * @inheritdoc
     */
    visit(pathFrom, preChildren, postChildren) {
        const path = this.fetchDeclaredPath(pathFrom);
        if (preChildren && preChildren(this, path)) {
            return false;
        }
        if (this.dataPartitions) {
            if (this.dataPartitions.visitArray(`${path}/dataPartitions/`, preChildren, postChildren)) {
                return true;
            }
        }
        if (this.dataPartitionPatterns) {
            if (this.dataPartitionPatterns.visitArray(`${path}/dataPartitionPatterns/`, preChildren, postChildren)) {
                return true;
            }
        }
        if (this.incrementalPartitions) {
            if (this.incrementalPartitions.visitArray(`${path}/incrementalPartitions/`, preChildren, postChildren)) {
                return true;
            }
        }
        if (this.incrementalPartitionPatterns) {
            if (this.incrementalPartitionPatterns.visitArray(`${path}/incrementalPartitionPatterns/`, preChildren, postChildren)) {
                return true;
            }
        }
        if (this.visitDef(path, preChildren, postChildren)) {
            return true;
        }
        if (postChildren && postChildren(this, path)) {
            return true;
        }
        return false;
    }
    /**
     * @inheritdoc
     */
    isDerivedFrom(base, resOpt) {
        return false; // makes no sense
    }
    /**
     * @inheritdoc
     */
    fileStatusCheckAsync(partitionCheckType = internal_1.partitionFileStatusCheckType.Full, incrementalType = internal_1.cdmIncrementalPartitionType.None) {
        return __awaiter(this, void 0, void 0, function* () {
            let adapter = this.ctx.corpus.storage.fetchAdapter(this.inDocument.namespace);
            let cacheContext = (adapter != null) ? adapter.createFileQueryCacheContext() : null;
            try {
                const fullPath = this.ctx.corpus.storage.createAbsoluteCorpusPath(this.entityPath, this.inDocument);
                const modifiedTime = yield this.ctx.corpus.computeLastModifiedTimeAsync(fullPath, this);
                // check patterns first as this is a more performant way of querying file modification times 
                // from ADLS and we can cache the times for reuse in the individual partition checks below
                if (partitionCheckType === internal_1.partitionFileStatusCheckType.Full || partitionCheckType === internal_1.partitionFileStatusCheckType.FullAndIncremental) {
                    for (const pattern of this.dataPartitionPatterns) {
                        if (pattern.isIncremental) {
                            internal_1.Logger.error(pattern.ctx, this.TAG, this.fileStatusCheckAsync.name, pattern.atCorpusPath, internal_1.cdmLogCode.ErrUnexpectedIncrementalPartitionTrait, internal_1.CdmDataPartitionPatternDefinition.name, pattern.fetchObjectDefinitionName(), internal_1.constants.INCREMENTAL_TRAIT_NAME, 'dataPartitionPatterns');
                        }
                        else {
                            yield pattern.fileStatusCheckAsync();
                        }
                    }
                    for (const partition of this.dataPartitions) {
                        if (partition.isIncremental) {
                            internal_1.Logger.error(partition.ctx, this.TAG, this.fileStatusCheckAsync.name, partition.atCorpusPath, internal_1.cdmLogCode.ErrUnexpectedIncrementalPartitionTrait, internal_1.CdmDataPartitionDefinition.name, partition.fetchObjectDefinitionName(), internal_1.constants.INCREMENTAL_TRAIT_NAME, 'dataPartitions');
                        }
                        else {
                            yield partition.fileStatusCheckAsync();
                        }
                    }
                }
                if (partitionCheckType === internal_1.partitionFileStatusCheckType.Incremental || partitionCheckType === internal_1.partitionFileStatusCheckType.FullAndIncremental) {
                    for (const pattern of this.incrementalPartitionPatterns) {
                        if (this.shouldCallFileStatusCheck(incrementalType, true, pattern)) {
                            yield pattern.fileStatusCheckAsync();
                        }
                    }
                    for (const partition of this.incrementalPartitions) {
                        if (this.shouldCallFileStatusCheck(incrementalType, false, partition)) {
                            yield partition.fileStatusCheckAsync();
                        }
                    }
                }
                this.lastFileStatusCheckTime = new Date();
                this.setLastFileModifiedTime(timeUtils.maxTime(modifiedTime, this.lastFileModifiedTime));
                yield this.reportMostRecentTimeAsync(this.lastFileModifiedTime);
            }
            finally {
                if (cacheContext != null) {
                    cacheContext.dispose();
                }
            }
        });
    }
    /**
     * @internal
     * Determine if calling FileStatusCheckAsync on the given pattern or the given partition is needed.
     */
    shouldCallFileStatusCheck(incrementalType, isPattern, patternOrPartitionObj) {
        var _a;
        var update = true;
        var traitRef = patternOrPartitionObj.exhibitsTraits.item(internal_1.constants.INCREMENTAL_TRAIT_NAME);
        if (traitRef === undefined) {
            internal_1.Logger.error(patternOrPartitionObj.ctx, this.TAG, this.shouldCallFileStatusCheck.name, patternOrPartitionObj.atCorpusPath, internal_1.cdmLogCode.ErrMissingIncrementalPartitionTrait, isPattern ? internal_1.CdmDataPartitionPatternDefinition.name : internal_1.CdmDataPartitionDefinition.name, patternOrPartitionObj.fetchObjectDefinitionName(), internal_1.constants.INCREMENTAL_TRAIT_NAME, isPattern ? 'incrementalPartitionPatterns' : 'incrementalPartitions');
        }
        else {
            // None means update by default
            if (incrementalType == internal_1.cdmIncrementalPartitionType.None) {
                return update;
            }
            var traitRefIncrementalTypeValue = (_a = traitRef.arguments) === null || _a === void 0 ? void 0 : _a.fetchValue('type');
            if (traitRefIncrementalTypeValue === undefined) {
                update = false;
                internal_1.Logger.error(patternOrPartitionObj.ctx, this.TAG, this.shouldCallFileStatusCheck.name, patternOrPartitionObj.atCorpusPath, internal_1.cdmLogCode.ErrTraitArgumentMissing, 'type', internal_1.constants.INCREMENTAL_TRAIT_NAME, patternOrPartitionObj.fetchObjectDefinitionName());
            }
            else if (typeof traitRefIncrementalTypeValue !== 'string') {
                update = false;
                internal_1.Logger.error(patternOrPartitionObj.ctx, this.TAG, this.shouldCallFileStatusCheck.name, patternOrPartitionObj.atCorpusPath, internal_1.cdmLogCode.ErrTraitInvalidArgumentValueType, 'type', internal_1.constants.INCREMENTAL_TRAIT_NAME, patternOrPartitionObj.fetchObjectDefinitionName());
            }
            else {
                const traitRefIncrementalTypeValueStr = traitRefIncrementalTypeValue.toString();
                if (Object.values(internal_1.cdmIncrementalPartitionType).includes(traitRefIncrementalTypeValueStr)) {
                    update = internal_1.cdmIncrementalPartitionType[traitRefIncrementalTypeValueStr] === incrementalType;
                }
                else {
                    update = false;
                    internal_1.Logger.error(patternOrPartitionObj.ctx, this.TAG, this.shouldCallFileStatusCheck.name, patternOrPartitionObj.atCorpusPath, internal_1.cdmLogCode.ErrEnumConversionFailure, traitRefIncrementalTypeValue, 'cdmIncrementalPartitionType', `'parameter 'type' of trait '${internal_1.constants.INCREMENTAL_TRAIT_NAME}' from '${patternOrPartitionObj.fetchObjectDefinitionName()}'`);
                }
            }
        }
        return update;
    }
    /**
     * @inheritdoc
     */
    reportMostRecentTimeAsync(childTime) {
        return __awaiter(this, void 0, void 0, function* () {
            this.lastChildFileModifiedTime = childTime;
            const mostRecentAtThisLevel = timeUtils.maxTime(childTime, this.lastFileModifiedTime);
            if (this.owner.reportMostRecentTimeAsync && mostRecentAtThisLevel) {
                yield this.owner.reportMostRecentTimeAsync(mostRecentAtThisLevel);
            }
        });
    }
    /**
     * @internal
     * Creates a data partition object using the input, should be called by DataPartitionPattern object
     * This function doesn't check if the data partition exists.
     */
    createDataPartitionFromPattern(filePath, exhibitsTraits, args, schema, modifiedTime, isIncrementalPartition = false, incrementPartitionPatternName = undefined) {
        const newPartition = this.ctx.corpus.MakeObject(internal_1.cdmObjectType.dataPartitionDef);
        newPartition.location = filePath;
        newPartition.specializedSchema = schema;
        newPartition.lastFileModifiedTime = modifiedTime;
        newPartition.lastFileStatusCheckTime = new Date();
        for (const trait of exhibitsTraits) {
            newPartition.exhibitsTraits.push(trait.copy());
        }
        newPartition.arguments = new Map(args);
        if (!isIncrementalPartition) {
            this.dataPartitions.push(newPartition);
        }
        else {
            if (!StringUtils_1.StringUtils.isNullOrWhiteSpace(incrementPartitionPatternName)) {
                newPartition.exhibitsTraits.item(internal_1.constants.INCREMENTAL_TRAIT_NAME).arguments.push(internal_1.constants.INCREMENTAL_PATTERN_PARAMETER_NAME, incrementPartitionPatternName);
            }
            this.incrementalPartitions.push(newPartition);
        }
    }
    setLastFileModifiedTime(value) {
        this.setLastFileModifiedOldTime(this.lastFileModifiedTime);
        this.lastFileModifiedTime = value;
    }
    getlastFileModifiedTime() {
        return this.lastFileModifiedTime;
    }
    setLastFileModifiedOldTime(value) {
        this.lastFileModifiedOldTime = value;
    }
    getlastFileModifiedOldTime() {
        return this.lastFileModifiedOldTime;
    }
    resetLastFileModifiedOldTime() {
        this.setLastFileModifiedOldTime(null);
    }
}
exports.CdmLocalEntityDeclarationDefinition = CdmLocalEntityDeclarationDefinition;
//# sourceMappingURL=CdmLocalEntityDeclarationDefinition.js.map