"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ActionImageService = void 0;
const tslib_1 = require("tslib");
const core_1 = require("@loopback/core");
const lodash_1 = require("lodash");
const action_entity_service_1 = require("../../services/action-entity/action-entity.service");
const object_node_service_1 = require("../../services/object-node/object-node.service");
const application_error_1 = require("./../../helper/application-error");
const entity_name_1 = require("./../../models/entity-name");
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 action_tree_service_1 = require("./../../services/object-tree/action-tree.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 content_image_const_1 = require("./content-image.const");
const intercept_image_service_1 = require("./intercept-image.service");
const transient_image_service_1 = require("./transient-image.service");
let ActionImageService = class ActionImageService {
    constructor(actionEntityService, objectNodeService, objectTypeService, insideRestService, uriCompleteService, objectNodeDefinitionService, transientImageService, interceptImageService, transientNodeService) {
        this.actionEntityService = actionEntityService;
        this.objectNodeService = objectNodeService;
        this.objectTypeService = objectTypeService;
        this.insideRestService = insideRestService;
        this.uriCompleteService = uriCompleteService;
        this.objectNodeDefinitionService = objectNodeDefinitionService;
        this.transientImageService = transientImageService;
        this.interceptImageService = interceptImageService;
        this.transientNodeService = transientNodeService;
        this.actionEntityService.registerNewMethodFunction(content_image_const_1.CONTENT_IMAGE_PROVIDER, ActionImageService.name, 'Load and create several Image entities in an Image Gallery', entity_name_1.EntityName.objectNode, 'load', content_image_const_1.IMAGE_GALLERY_TYPE.name, this.loadImageGalleryNode.bind(this), 'create');
        this.actionEntityService.registerNewMethodFunction(content_image_const_1.CONTENT_IMAGE_PROVIDER, ActionImageService.name, 'Load and create several Image entities in a referenced Image Gallery', entity_name_1.EntityName.objectNode, 'load', content_image_const_1.IMAGE_GALLERY_REFERRER_TYPE.name, this.loadImageGalleryReferrerNode.bind(this), 'create');
        this.actionEntityService.registerNewMethodFunction(content_image_const_1.CONTENT_IMAGE_PROVIDER, ActionImageService.name, 'Create new Image Gallery for a gallery referrer', entity_name_1.EntityName.objectNode, 'createGallery', content_image_const_1.IMAGE_GALLERY_REFERRER_TYPE.name, this.createGalleryImageGalleryReferrerNode.bind(this), 'create');
        this.actionEntityService.registerNewMethodFunction(content_image_const_1.CONTENT_IMAGE_PROVIDER, ActionImageService.name, 'Configure an Image Gallery for a gallery referrer', entity_name_1.EntityName.objectNode, 'configureGallery', content_image_const_1.IMAGE_GALLERY_REFERRER_TYPE.name, this.configureGalleryImageGalleryReferrerNode.bind(this), 'update');
        this.actionEntityService.registerNewMethodFunction(content_image_const_1.CONTENT_IMAGE_PROVIDER, ActionImageService.name, 'Reset image position and/or date', entity_name_1.EntityName.objectNode, 'resetInfo', content_image_const_1.IMAGE_TYPE.name, this.resetInfoImageNode.bind(this), 'update');
        this.actionEntityService.registerNewMethodFunction(content_image_const_1.CONTENT_IMAGE_PROVIDER, ActionImageService.name, 'Reset images order', entity_name_1.EntityName.objectNode, 'resetOrder', content_image_const_1.IMAGE_GALLERY_TYPE.name, this.resetOrderImageGalleryNode.bind(this), 'update');
    }
    async resetOrderImageGalleryNode(entity, args, ctx) {
        const galleryTree = await this.insideRestService.read(this.uriCompleteService.getUri(entity_name_1.EntityName.objectTree, entity.id, ctx), ctx);
        await new action_tree_service_1.SortMethod(this.objectNodeService).runMethod(galleryTree, galleryTree.children
            .sort((a, b) => {
            if (!a.treeNode.imageDate && !b.treeNode.imageDate) {
                return a.treeNode.index - b.treeNode.index;
            }
            if (!a.treeNode.imageDate || !b.treeNode.imageDate) {
                return !a.treeNode.imageDate ? 1 : -1;
            }
            return Date.parse(a.treeNode.imageDate) <
                Date.parse(b.treeNode.imageDate)
                ? -1
                : 1;
        })
            .map((tree) => tree.treeNode.id), ctx);
        return this.actionEntityService.getEntity(entity_name_1.EntityName.objectTree, entity.id, application_service_1.CurrentContext.get(ctx, {}));
    }
    async resetInfoImageNode(entity, args, ctx) {
        if (args.position || args.date) {
            const update = {};
            if (entity.contentImageId && !entity.contentImage) {
                await this.transientNodeService.completeReturnedEntity(entity, ctx);
            }
            const exif = (await this.transientImageService.getImageExif(entity));
            if (args.position) {
                const imagePosition = this.transientImageService.getPositionFromExif(exif);
                if (imagePosition) {
                    update.imagePosition = imagePosition;
                }
            }
            if (args.date) {
                const imageDate = this.transientImageService.getImageDateFromExif(exif);
                if (imageDate) {
                    update.imageDate = imageDate;
                }
            }
            if (0 < Object.keys(update).length) {
                await this.objectNodeService.modifyById(entity.id, update, ctx);
            }
        }
        return this.actionEntityService.getEntity(entity_name_1.EntityName.objectNode, entity.id, application_service_1.CurrentContext.get(ctx, {}));
    }
    async createImage(image, parent, ctx, parentType, title) {
        await this.interceptImageService.checkAndReduceImageSize(image);
        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 = image.name.split('.');
        if (1 < nameParts.length) {
            nameParts.pop();
        }
        const exif = (await this.transientImageService.getImageExif({
            contentImage: image,
        }));
        const position = this.transientImageService.getPositionFromExif(exif);
        const date = this.transientImageService.getImageDateFromExif(exif);
        return this.objectNodeService.add({
            name: title ? title : nameParts.join('.'),
            imagePosition: position,
            imageDate: date,
            parentNodeId: parent.id,
            objectTypeId: content_image_const_1.IMAGE_TYPE.name,
            contentImage: image,
        }, childCtx, false, true, true);
    }
    async loadImageGalleryNode(gallery, args, ctx) {
        const images = args;
        for (const image of images.images) {
            await this.createImage(image, ctx.nodeContext.node.value, ctx, ctx.nodeContext.objectType.value, images.title);
        }
        return this.actionEntityService.getEntity(entity_name_1.EntityName.objectTree, gallery.id, application_service_1.CurrentContext.get(ctx, {}));
    }
    async configureGalleryImageGalleryReferrerNode(objectNode, args, ctx) {
        const imageGalleryObjectTreeId = args.imageGalleryObjectTreeId;
        if (undefined === imageGalleryObjectTreeId ||
            '' === imageGalleryObjectTreeId) {
            throw application_error_1.ApplicationError.missingParameter(imageGalleryObjectTreeId);
        }
        await this.objectNodeService.modifyById(objectNode.id, { imageGalleryObjectTreeId: imageGalleryObjectTreeId }, application_service_1.CurrentContext.get(ctx));
        return this.actionEntityService.getEntity(entity_name_1.EntityName.objectNode, objectNode.id, application_service_1.CurrentContext.get(ctx, {}));
    }
    async createGalleryImageGalleryReferrerNode(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 galleries = await this.transientImageService.getImageGalleriesParents(objectNode);
            if (!galleries || 0 === galleries.length) {
                throw application_error_1.ApplicationError.missing({ object: content_image_const_1.IMAGE_GALLERIES_TYPE.name });
            }
            parentId = galleries[0].id;
        }
        let childTypeId = creationArguments.childTypeId;
        const refererType = await this.objectTypeService.searchById(objectNode.objectTypeId);
        if (!refererType.definition.properties.imageGalleryObjectTreeId.oneOfTree) {
            throw application_error_1.ApplicationError.forbidden();
        }
        const oneOfTreeOptions = refererType.definition.properties.imageGalleryObjectTreeId.oneOfTree.filter((referencedTree) => !referencedTree.namespaceType);
        const referredTypes = oneOfTreeOptions.map((oneOfTree) => oneOfTree.treeType);
        let galleryTypes = [];
        for (const referredType of referredTypes) {
            galleryTypes.push(...(await this.objectTypeService.getImplementingTypes(referredType)));
        }
        if (!childTypeId || '' === childTypeId) {
            const parentGalleryTree = (await this.insideRestService.read(this.uriCompleteService.getUri(entity_name_1.EntityName.objectTree, parentId, ctx), ctx));
            if (!((_b = (_a = parentGalleryTree.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_image_const_1.IMAGE_GALLERIES_TYPE.name,
                    parentId: parentId,
                    childType: content_image_const_1.IMAGE_GALLERY_TYPE.name,
                });
            }
            const childTypeIds = Object.keys(parentGalleryTree.entityCtx.actions.creations);
            galleryTypes = galleryTypes.filter((type) => -1 < childTypeIds.indexOf(type));
            if (0 === childTypeIds.length) {
                throw application_error_1.ApplicationError.missing({
                    object: content_image_const_1.IMAGE_GALLERIES_TYPE.name,
                    parentId: parentId,
                    childType: content_image_const_1.IMAGE_GALLERY_TYPE.name,
                });
            }
            childTypeId = galleryTypes[0];
        }
        if (-1 === galleryTypes.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 newGallery = 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(newGallery.parentOwnerId, application_service_1.CurrentContext.get(ctx));
        const namespace = await this.objectNodeService.getNode(newGallery.parentNamespaceId, application_service_1.CurrentContext.get(ctx));
        const imageGalleryObjectTreeId = this.objectNodeDefinitionService.getTreeIdFromTreeOption(oneOfTreeOption, owner, namespace, newGallery);
        await this.objectNodeService.modifyById(objectNode.id, { imageGalleryObjectTreeId: imageGalleryObjectTreeId }, 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 loadImageGalleryReferrerNode(objectNode, args, ctx) {
        if (objectNode.imageGalleryObjectTreeId) {
            const imageGalleryParts = objectNode.imageGalleryObjectTreeId.split('/');
            const imageGalleryNode = await this.objectNodeService.searchTree(imageGalleryParts[1], imageGalleryParts[2], imageGalleryParts[3], imageGalleryParts[4], imageGalleryParts[5], imageGalleryParts[6]);
            if (imageGalleryNode) {
                let selectedImages = undefined;
                let initialSelectedImagesCount = 0;
                const implementedTypes = await this.objectTypeService.getImplementedTypes(objectNode.objectTypeId);
                if (-1 < lodash_1.indexOf(implementedTypes, content_image_const_1.IMAGE_GALLERY_SELECTOR_TYPE.name)) {
                    selectedImages = objectNode.selectedImages
                        ? objectNode.selectedImages
                        : [];
                    initialSelectedImagesCount = selectedImages.length;
                }
                const images = args;
                for (const image of images.images) {
                    const imageObject = await this.createImage(image, imageGalleryNode, ctx, undefined, images.title);
                    if (imageObject && selectedImages) {
                        selectedImages.push(imageObject.name);
                    }
                }
                if (selectedImages &&
                    selectedImages.length > initialSelectedImagesCount) {
                    await this.objectNodeService.modifyById(objectNode.id, { selectedImages }, ctx);
                }
                return [
                    await this.actionEntityService.getEntity(entity_name_1.EntityName.objectTree, imageGalleryNode.id, application_service_1.CurrentContext.get(ctx, {})),
                    await this.actionEntityService.getEntity(entity_name_1.EntityName.objectNode, objectNode.id, ctx),
                ];
            }
        }
    }
};
ActionImageService = 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_image_service_1.TransientImageService)),
    tslib_1.__param(7, core_1.service(intercept_image_service_1.InterceptImageService)),
    tslib_1.__param(8, core_1.service(transient_node_service_1.TransientNodeService)),
    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_image_service_1.TransientImageService,
        intercept_image_service_1.InterceptImageService,
        transient_node_service_1.TransientNodeService])
], ActionImageService);
exports.ActionImageService = ActionImageService;
//# sourceMappingURL=action-image.service.js.map