"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ActionFileService = void 0;
const tslib_1 = require("tslib");
const core_1 = require("@loopback/core");
const lodash_1 = require("lodash");
const application_error_1 = require("../../helper/application-error");
const entity_name_1 = require("../../models/entity-name");
const action_entity_service_1 = require("../../services/action-entity/action-entity.service");
const application_service_1 = require("../../services/application.service");
const object_node_definition_service_1 = require("../../services/entity-definition/object-node-definition.service");
const inside_rest_service_1 = require("../../services/inside-rest/inside-rest.service");
const object_node_service_1 = require("../../services/object-node/object-node.service");
const object_type_service_1 = require("../../services/object-type.service");
const transient_node_service_1 = require("../../services/transient-entity/transient-node.service");
const uri_complete_service_1 = require("../../services/uri-complete/uri-complete.service");
const location_service_1 = require("../location/location.service");
const content_file_const_1 = require("./content-file.const");
const intercept_file_service_1 = require("./intercept-file.service");
const transient_file_service_1 = require("./transient-file.service");
let ActionFileService = class ActionFileService {
    constructor(actionEntityService, objectNodeService, objectTypeService, insideRestService, uriCompleteService, objectNodeDefinitionService, transientFileService, interceptFileService, transientNodeService, locationService) {
        this.actionEntityService = actionEntityService;
        this.objectNodeService = objectNodeService;
        this.objectTypeService = objectTypeService;
        this.insideRestService = insideRestService;
        this.uriCompleteService = uriCompleteService;
        this.objectNodeDefinitionService = objectNodeDefinitionService;
        this.transientFileService = transientFileService;
        this.interceptFileService = interceptFileService;
        this.transientNodeService = transientNodeService;
        this.locationService = locationService;
        this.actionEntityService.registerNewMethodFunction(content_file_const_1.CONTENT_FILE_PROVIDER, ActionFileService.name, 'Load and create several File entities in an File Directory', entity_name_1.EntityName.objectNode, 'load', content_file_const_1.FILES_DIRECTORY_TYPE.name, this.loadFileDirectoryNode.bind(this), 'create');
        this.actionEntityService.registerNewMethodFunction(content_file_const_1.CONTENT_FILE_PROVIDER, ActionFileService.name, 'Load and create several File entities in a referenced File Directory', entity_name_1.EntityName.objectNode, 'load', content_file_const_1.FILE_DIRECTORY_REFERRER_TYPE.name, this.loadFileDirectoryReferrerNode.bind(this), 'create');
        this.actionEntityService.registerNewMethodFunction(content_file_const_1.CONTENT_FILE_PROVIDER, ActionFileService.name, 'Create new File Directory for a directory referrer', entity_name_1.EntityName.objectNode, 'createDirectory', content_file_const_1.FILE_DIRECTORY_REFERRER_TYPE.name, this.createDirectoryFileDirectoryReferrerNode.bind(this), 'create');
        this.actionEntityService.registerNewMethodFunction(content_file_const_1.CONTENT_FILE_PROVIDER, ActionFileService.name, 'Configure an File Directory for a directory referrer', entity_name_1.EntityName.objectNode, 'configureDirectory', content_file_const_1.FILE_DIRECTORY_REFERRER_TYPE.name, this.configureDirectoryFileDirectoryReferrerNode.bind(this), 'update');
    }
    async createFile(file, parent, ctx, parentType, title) {
        const childCtx = application_service_1.CurrentContext.get(ctx, {
            nodeContext: {
                parent: new application_service_1.ExpectedValue(parent),
                parentType: new application_service_1.ExpectedValue(parentType),
            },
        });
        const nameParts = file.name.split('.');
        if (1 < nameParts.length) {
            nameParts.pop();
        }
        return this.objectNodeService.add({
            name: title ? title : nameParts.join('.'),
            parentNodeId: parent.id,
            objectTypeId: content_file_const_1.FILE_TYPE.name,
            contentFile: file,
        }, childCtx, false, true, true);
    }
    async loadFileDirectoryNode(directory, args, ctx) {
        const files = args;
        for (const file of files.files) {
            await this.createFile(file, ctx.nodeContext.node.value, ctx, ctx.nodeContext.objectType.value, files.title);
        }
        return this.actionEntityService.getEntity(entity_name_1.EntityName.objectTree, directory.id, application_service_1.CurrentContext.get(ctx, {}));
    }
    async configureDirectoryFileDirectoryReferrerNode(objectNode, args, ctx) {
        const fileDirectoryObjectTreeId = args.fileDirectoryObjectTreeId;
        if (undefined === fileDirectoryObjectTreeId ||
            '' === fileDirectoryObjectTreeId) {
            throw application_error_1.ApplicationError.missingParameter(fileDirectoryObjectTreeId);
        }
        await this.objectNodeService.modifyById(objectNode.id, { fileDirectoryObjectTreeId: fileDirectoryObjectTreeId }, application_service_1.CurrentContext.get(ctx));
        return this.actionEntityService.getEntity(entity_name_1.EntityName.objectNode, objectNode.id, application_service_1.CurrentContext.get(ctx, {}));
    }
    async createDirectoryFileDirectoryReferrerNode(objectNode, args, ctx) {
        var _a, _b;
        const creationArguments = args;
        let name = creationArguments.name;
        if (!name || '' === name) {
            name = objectNode.title || objectNode.name;
        }
        let parentId = creationArguments.parentId;
        if (!parentId || '' === parentId) {
            const directories = await this.transientFileService.getFileDirectoriesParents(objectNode);
            if (!directories || 0 === directories.length) {
                throw application_error_1.ApplicationError.missing({ object: content_file_const_1.FILE_DIRECTORIES_TYPE.name });
            }
            parentId = directories[0].id;
        }
        let childTypeId = creationArguments.childTypeId;
        const refererType = await this.objectTypeService.searchById(objectNode.objectTypeId);
        if (!refererType.definition.properties.fileDirectoryObjectTreeId.oneOfTree) {
            throw application_error_1.ApplicationError.forbidden();
        }
        const oneOfTreeOptions = refererType.definition.properties.fileDirectoryObjectTreeId.oneOfTree.filter((referencedTree) => !referencedTree.namespaceType);
        const referredTypes = oneOfTreeOptions.map((oneOfTree) => oneOfTree.treeType);
        let directoryTypes = [];
        for (const referredType of referredTypes) {
            directoryTypes.push(...(await this.objectTypeService.getImplementingTypes(referredType)));
        }
        if (!childTypeId || '' === childTypeId) {
            const parentDirectoryTree = (await this.insideRestService.read(this.uriCompleteService.getUri(entity_name_1.EntityName.objectTree, parentId, ctx), ctx));
            if (!((_b = (_a = parentDirectoryTree.entityCtx) === null || _a === void 0 ? void 0 : _a.actions) === null || _b === void 0 ? void 0 : _b.creations)) {
                throw application_error_1.ApplicationError.missing({
                    object: content_file_const_1.FILE_DIRECTORIES_TYPE.name,
                    parentId: parentId,
                    childType: content_file_const_1.FILES_DIRECTORY_TYPE.name,
                });
            }
            const childTypeIds = Object.keys(parentDirectoryTree.entityCtx.actions.creations);
            directoryTypes = directoryTypes.filter((type) => -1 < childTypeIds.indexOf(type));
            if (0 === childTypeIds.length) {
                throw application_error_1.ApplicationError.missing({
                    object: content_file_const_1.FILE_DIRECTORIES_TYPE.name,
                    parentId: parentId,
                    childType: content_file_const_1.FILES_DIRECTORY_TYPE.name,
                });
            }
            childTypeId = directoryTypes[0];
        }
        if (-1 === directoryTypes.indexOf(childTypeId)) {
            throw application_error_1.ApplicationError.unauthorizedValue({ childTypeId: childTypeId });
        }
        for (let index = oneOfTreeOptions.length - 1; index--; index >= 0) {
            if (-1 ===
                lodash_1.indexOf(await this.objectTypeService.getImplementingTypes(oneOfTreeOptions[index].treeType), childTypeId)) {
                oneOfTreeOptions.splice(index, 1);
            }
        }
        if (0 === oneOfTreeOptions.length) {
            throw application_error_1.ApplicationError.unauthorizedValue({ childTypeId: childTypeId });
        }
        const oneOfTreeOption = oneOfTreeOptions[0];
        const newDirectory = await this.objectNodeService.add({ parentNodeId: parentId, objectTypeId: childTypeId, name: name }, application_service_1.CurrentContext.get(ctx), false, true, true);
        const owner = await this.objectNodeService.getNode(newDirectory.parentOwnerId, application_service_1.CurrentContext.get(ctx));
        const namespace = await this.objectNodeService.getNode(newDirectory.parentNamespaceId, application_service_1.CurrentContext.get(ctx));
        const fileDirectoryObjectTreeId = this.objectNodeDefinitionService.getTreeIdFromTreeOption(oneOfTreeOption, owner, namespace, newDirectory);
        await this.objectNodeService.modifyById(objectNode.id, { fileDirectoryObjectTreeId: fileDirectoryObjectTreeId }, application_service_1.CurrentContext.get(ctx));
        return [
            await this.actionEntityService.getEntity(entity_name_1.EntityName.objectTree, parentId, application_service_1.CurrentContext.get(ctx, {})),
            await this.actionEntityService.getEntity(entity_name_1.EntityName.objectNode, objectNode.id, application_service_1.CurrentContext.get(ctx, {})),
        ];
    }
    async loadFileDirectoryReferrerNode(objectNode, args, ctx) {
        if (objectNode.fileDirectoryObjectTreeId) {
            const fileDirectoryParts = objectNode.fileDirectoryObjectTreeId.split('/');
            const fileDirectoryNode = await this.objectNodeService.searchTree(fileDirectoryParts[1], fileDirectoryParts[2], fileDirectoryParts[3], fileDirectoryParts[4], fileDirectoryParts[5], fileDirectoryParts[6]);
            if (fileDirectoryNode) {
                let selectedFiles = undefined;
                let initialSelectedFilesCount = 0;
                const implementedTypes = await this.objectTypeService.getImplementedTypes(objectNode.objectTypeId);
                if (-1 < lodash_1.indexOf(implementedTypes, content_file_const_1.FILE_DIRECTORY_SELECTOR_TYPE.name)) {
                    selectedFiles = objectNode.selectedFiles
                        ? objectNode.selectedFiles
                        : [];
                    initialSelectedFilesCount = selectedFiles.length;
                }
                const files = args;
                for (const file of files.files) {
                    const fileObject = await this.createFile(file, fileDirectoryNode, ctx, undefined, files.title);
                    if (fileObject && selectedFiles) {
                        selectedFiles.push(fileObject.name);
                    }
                }
                if (selectedFiles && selectedFiles.length > initialSelectedFilesCount) {
                    await this.objectNodeService.modifyById(objectNode.id, { selectedFiles }, ctx);
                }
                return [
                    await this.actionEntityService.getEntity(entity_name_1.EntityName.objectTree, fileDirectoryNode.id, application_service_1.CurrentContext.get(ctx, {})),
                    await this.actionEntityService.getEntity(entity_name_1.EntityName.objectNode, objectNode.id, ctx),
                ];
            }
        }
    }
};
ActionFileService = tslib_1.__decorate([
    tslib_1.__param(0, core_1.service(action_entity_service_1.ActionEntityService)),
    tslib_1.__param(1, core_1.service(object_node_service_1.ObjectNodeService)),
    tslib_1.__param(2, core_1.service(object_type_service_1.ObjectTypeService)),
    tslib_1.__param(3, core_1.service(inside_rest_service_1.InsideRestService)),
    tslib_1.__param(4, core_1.service(uri_complete_service_1.UriCompleteService)),
    tslib_1.__param(5, core_1.service(object_node_definition_service_1.ObjectNodeDefinitionService)),
    tslib_1.__param(6, core_1.service(transient_file_service_1.TransientFileService)),
    tslib_1.__param(7, core_1.service(intercept_file_service_1.InterceptFileService)),
    tslib_1.__param(8, core_1.service(transient_node_service_1.TransientNodeService)),
    tslib_1.__param(9, core_1.service(location_service_1.LocationService)),
    tslib_1.__metadata("design:paramtypes", [action_entity_service_1.ActionEntityService,
        object_node_service_1.ObjectNodeService,
        object_type_service_1.ObjectTypeService,
        inside_rest_service_1.InsideRestService,
        uri_complete_service_1.UriCompleteService,
        object_node_definition_service_1.ObjectNodeDefinitionService,
        transient_file_service_1.TransientFileService,
        intercept_file_service_1.InterceptFileService,
        transient_node_service_1.TransientNodeService,
        location_service_1.LocationService])
], ActionFileService);
exports.ActionFileService = ActionFileService;
//# sourceMappingURL=action-file.service.js.map