var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
import ClusterKeyAuthorization from "../../../../Middleware/ClusterKeyAuthorization";
import WorkflowService from "../../../../Services/WorkflowService";
import logger from "../../../../Utils/Logger";
import Response from "../../../../Utils/Response";
import TriggerCode from "../../TriggerCode";
import BaseModel from "../../../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
import LIMIT_MAX from "../../../../../Types/Database/LimitMax";
import BadDataException from "../../../../../Types/Exception/BadDataException";
import JSONFunctions from "../../../../../Types/JSONFunctions";
import ObjectID from "../../../../../Types/ObjectID";
import Text from "../../../../../Types/Text";
import BaseModelComponents from "../../../../../Types/Workflow/Components/BaseModel";
import CaptureSpan from "../../../../Utils/Telemetry/CaptureSpan";
export default class OnTriggerBaseModel extends TriggerCode {
    constructor(modelService, type) {
        super();
        this.modelId = "";
        this.type = "";
        this.service = null;
        this.service = modelService;
        this.modelId = `${Text.pascalCaseToDashes(modelService.getModel().tableName)}`;
        this.type = type;
        const BaseModelComponent = BaseModelComponents.getComponents(modelService.getModel()).find((i) => {
            return i.id === `${this.modelId}-${this.type}`;
        });
        if (!BaseModelComponent) {
            throw new BadDataException("On Create trigger component for " +
                modelService.getModel().tableName +
                " not found.");
        }
        this.setMetadata(BaseModelComponent);
    }
    async init(props) {
        props.router.get(`/model/:projectId/${this.modelId}/${this.type}`, ClusterKeyAuthorization.isAuthorizedServiceMiddleware, async (req, res, next) => {
            try {
                await this.initTrigger(req, res, props);
            }
            catch (err) {
                return next(err);
            }
        });
        props.router.post(`/model/:projectId/${this.modelId}/${this.type}`, ClusterKeyAuthorization.isAuthorizedServiceMiddleware, async (req, res, next) => {
            try {
                await this.initTrigger(req, res, props);
            }
            catch (err) {
                return next(err);
            }
        });
    }
    async run(args, options) {
        let data = args["data"];
        if (!data) {
            data = {};
        }
        if (args["_id"]) {
            data["_id"] = args["_id"];
        }
        const miscData = (data === null || data === void 0 ? void 0 : data["miscData"]) || {};
        const successPort = this.getMetadata().outPorts.find((p) => {
            return p.id === "success";
        });
        if (!successPort) {
            throw options.onError(new BadDataException("Success port not found"));
        }
        if (!data["_id"] ||
            !args["select"] ||
            Object.keys(args["select"]).length === 0) {
            return {
                returnValues: Object.assign({ model: data
                        ? BaseModel.toJSON(data, this.service.modelType)
                        : null }, (miscData || {})),
                executePort: successPort,
            };
        }
        let select = args["select"];
        const runLogAttributes = {
            projectId: options.projectId.toString(),
            workflowId: options.workflowId.toString(),
        };
        logger.debug("Select: ", runLogAttributes);
        logger.debug(select, runLogAttributes);
        if (select && typeof select === "string") {
            select = JSONFunctions.parse(select);
        }
        /*
         * Convert string "true"/"false" values to booleans in select.
         * Workflow arguments may pass select values as strings (e.g. "true")
         * which causes TypeORM to iterate string characters as property indices.
         */
        if (select && typeof select === "object") {
            for (const key in select) {
                if (select[key] === "true") {
                    select[key] = true;
                }
                else if (select[key] === "false") {
                    select[key] = false;
                }
            }
        }
        const model = await this.service.findOneById({
            id: new ObjectID(data["_id"].toString()),
            props: {
                isRoot: true,
            },
            select: Object.assign({ _id: true }, select),
        });
        if (!model) {
            options.log("Model not found with id " + data["_id"].toString());
            throw new BadDataException(("Model not found with id " + data["_id"].toString()));
        }
        return {
            returnValues: {
                model: data
                    ? BaseModel.toJSON(model, this.service.modelType)
                    : null,
            },
            executePort: successPort,
        };
    }
    async initTrigger(req, res, props) {
        var _a, _b, _c;
        // get all the enabled workflows with this trigger.
        Response.sendJsonObjectResponse(req, res, { status: "Triggered" });
        const workflows = await WorkflowService.findBy({
            query: {
                triggerId: this.getMetadata().id,
                projectId: new ObjectID(req.params["projectId"]),
                isEnabled: true,
            },
            props: {
                isRoot: true,
            },
            limit: LIMIT_MAX,
            skip: 0,
            select: {
                _id: true,
                triggerArguments: true,
            },
        });
        const promises = [];
        const requestData = req.body.data;
        for (const workflow of workflows) {
            /// Run Graph.
            if (this.type === "on-update" &&
                ((_a = workflow.triggerArguments) === null || _a === void 0 ? void 0 : _a["listen-on"])) {
                let listenOn = (_b = workflow.triggerArguments) === null || _b === void 0 ? void 0 : _b["listen-on"];
                const miscData = (requestData === null || requestData === void 0 ? void 0 : requestData["miscData"]) || {};
                if (listenOn &&
                    Object.keys(listenOn).length > 0 &&
                    miscData &&
                    Object.keys(miscData).length > 0) {
                    try {
                        if (typeof listenOn === "string") {
                            listenOn = JSON.parse(listenOn);
                        }
                    }
                    catch (err) {
                        logger.error(err, {
                            projectId: req.params["projectId"],
                            workflowId: (_c = workflow.id) === null || _c === void 0 ? void 0 : _c.toString(),
                        });
                        continue;
                    }
                    const updatedFields = miscData["updatedFields"];
                    if (updatedFields && Object.keys(updatedFields).length > 0) {
                        let isUpdated = false;
                        for (const key in listenOn) {
                            if (updatedFields[key]) {
                                isUpdated = true;
                                break;
                            }
                        }
                        if (!isUpdated) {
                            continue;
                        }
                    }
                }
            }
            const executeWorkflow = {
                workflowId: workflow.id,
                returnValues: {
                    data: requestData,
                },
            };
            promises.push(props.executeWorkflow(executeWorkflow));
        }
        await Promise.all(promises);
    }
}
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], OnTriggerBaseModel.prototype, "init", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object, Object]),
    __metadata("design:returntype", Promise)
], OnTriggerBaseModel.prototype, "run", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object, Object, Object]),
    __metadata("design:returntype", Promise)
], OnTriggerBaseModel.prototype, "initTrigger", null);
//# sourceMappingURL=OnTriggerBaseModel.js.map