"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.promise = void 0;
/* eslint-disable no-param-reassign */
const types_1 = require("../../config/types");
const traverseFields_1 = require("./traverseFields");
const relationshipPromise_1 = __importDefault(require("../../richText/relationshipPromise"));
const relationshipPopulationPromise_1 = __importDefault(require("./relationshipPopulationPromise"));
// This function is responsible for the following actions, in order:
// - Remove hidden fields from response
// - Flatten locales into requested locale
// - Sanitize outgoing data (point field, etc)
// - Execute field hooks
// - Execute read access control
// - Populate relationships
const promise = async ({ currentDepth, depth, doc, field, fieldPromises, findMany, flattenLocales, overrideAccess, populationPromises, req, siblingDoc, showHiddenFields, }) => {
    var _a, _b, _c, _d, _e, _f;
    if ((0, types_1.fieldAffectsData)(field) && field.hidden && typeof siblingDoc[field.name] !== 'undefined' && !showHiddenFields) {
        delete siblingDoc[field.name];
    }
    const hasLocalizedValue = flattenLocales
        && (0, types_1.fieldAffectsData)(field)
        && (typeof siblingDoc[field.name] === 'object' && siblingDoc[field.name] !== null)
        && field.name
        && field.localized
        && req.locale !== 'all';
    if (hasLocalizedValue) {
        let localizedValue = siblingDoc[field.name][req.locale];
        if (typeof localizedValue === 'undefined' && req.fallbackLocale)
            localizedValue = siblingDoc[field.name][req.fallbackLocale];
        if (typeof localizedValue === 'undefined' && field.type === 'group')
            localizedValue = {};
        if (typeof localizedValue === 'undefined')
            localizedValue = null;
        siblingDoc[field.name] = localizedValue;
    }
    // Sanitize outgoing data
    switch (field.type) {
        case 'group': {
            // Fill groups with empty objects so fields with hooks within groups can populate
            // themselves virtually as necessary
            if (typeof siblingDoc[field.name] === 'undefined') {
                siblingDoc[field.name] = {};
            }
            break;
        }
        case 'richText': {
            if (((((_b = (_a = field.admin) === null || _a === void 0 ? void 0 : _a.elements) === null || _b === void 0 ? void 0 : _b.includes('relationship')) || ((_d = (_c = field.admin) === null || _c === void 0 ? void 0 : _c.elements) === null || _d === void 0 ? void 0 : _d.includes('upload'))) || !((_e = field === null || field === void 0 ? void 0 : field.admin) === null || _e === void 0 ? void 0 : _e.elements))) {
                populationPromises.push((0, relationshipPromise_1.default)({
                    currentDepth,
                    depth,
                    field,
                    overrideAccess,
                    req,
                    siblingDoc,
                    showHiddenFields,
                }));
            }
            break;
        }
        case 'point': {
            const pointDoc = siblingDoc[field.name];
            if (Array.isArray(pointDoc === null || pointDoc === void 0 ? void 0 : pointDoc.coordinates) && pointDoc.coordinates.length === 2) {
                siblingDoc[field.name] = pointDoc.coordinates;
            }
            break;
        }
        default: {
            break;
        }
    }
    if ((0, types_1.fieldAffectsData)(field)) {
        // Execute hooks
        if ((_f = field.hooks) === null || _f === void 0 ? void 0 : _f.afterRead) {
            await field.hooks.afterRead.reduce(async (priorHook, currentHook) => {
                await priorHook;
                const shouldRunHookOnAllLocales = field.localized
                    && (req.locale === 'all' || !flattenLocales)
                    && typeof siblingDoc[field.name] === 'object';
                if (shouldRunHookOnAllLocales) {
                    const hookPromises = Object.entries(siblingDoc[field.name]).map(([locale, value]) => (async () => {
                        const hookedValue = await currentHook({
                            value,
                            originalDoc: doc,
                            data: doc,
                            siblingData: siblingDoc[field.name],
                            operation: 'read',
                            req,
                        });
                        if (hookedValue !== undefined) {
                            siblingDoc[field.name][locale] = hookedValue;
                        }
                    })());
                    await Promise.all(hookPromises);
                }
                else {
                    const hookedValue = await currentHook({
                        data: doc,
                        findMany,
                        originalDoc: doc,
                        operation: 'read',
                        siblingData: siblingDoc[field.name],
                        req,
                        value: siblingDoc[field.name],
                    });
                    if (hookedValue !== undefined) {
                        siblingDoc[field.name] = hookedValue;
                    }
                }
            }, Promise.resolve());
        }
        // Execute access control
        if (field.access && field.access.read) {
            const result = overrideAccess ? true : await field.access.read({ req, id: doc.id, siblingData: siblingDoc, data: doc, doc });
            if (!result) {
                delete siblingDoc[field.name];
            }
        }
        if (field.type === 'relationship' || field.type === 'upload') {
            populationPromises.push((0, relationshipPopulationPromise_1.default)({
                currentDepth,
                depth,
                field,
                overrideAccess,
                req,
                showHiddenFields,
                siblingDoc,
            }));
        }
    }
    switch (field.type) {
        case 'group': {
            let groupDoc = siblingDoc[field.name];
            if (typeof siblingDoc[field.name] !== 'object')
                groupDoc = {};
            (0, traverseFields_1.traverseFields)({
                currentDepth,
                depth,
                doc,
                fieldPromises,
                fields: field.fields,
                findMany,
                flattenLocales,
                overrideAccess,
                populationPromises,
                req,
                siblingDoc: groupDoc,
                showHiddenFields,
            });
            break;
        }
        case 'array': {
            const rows = siblingDoc[field.name];
            if (Array.isArray(rows)) {
                rows.forEach((row, i) => {
                    (0, traverseFields_1.traverseFields)({
                        currentDepth,
                        depth,
                        doc,
                        fields: field.fields,
                        fieldPromises,
                        findMany,
                        flattenLocales,
                        overrideAccess,
                        populationPromises,
                        req,
                        siblingDoc: row || {},
                        showHiddenFields,
                    });
                });
            }
            break;
        }
        case 'blocks': {
            const rows = siblingDoc[field.name];
            if (Array.isArray(rows)) {
                rows.forEach((row, i) => {
                    const block = field.blocks.find((blockType) => blockType.slug === row.blockType);
                    if (block) {
                        (0, traverseFields_1.traverseFields)({
                            currentDepth,
                            depth,
                            doc,
                            fields: block.fields,
                            fieldPromises,
                            findMany,
                            flattenLocales,
                            overrideAccess,
                            populationPromises,
                            req,
                            siblingDoc: row || {},
                            showHiddenFields,
                        });
                    }
                });
            }
            break;
        }
        case 'row':
        case 'collapsible': {
            (0, traverseFields_1.traverseFields)({
                currentDepth,
                depth,
                doc,
                fieldPromises,
                fields: field.fields,
                findMany,
                flattenLocales,
                overrideAccess,
                populationPromises,
                req,
                siblingDoc,
                showHiddenFields,
            });
            break;
        }
        case 'tabs': {
            field.tabs.forEach((tab) => {
                (0, traverseFields_1.traverseFields)({
                    currentDepth,
                    depth,
                    doc,
                    fieldPromises,
                    fields: tab.fields,
                    findMany,
                    flattenLocales,
                    overrideAccess,
                    populationPromises,
                    req,
                    siblingDoc,
                    showHiddenFields,
                });
            });
            break;
        }
        default: {
            break;
        }
    }
};
exports.promise = promise;
//# sourceMappingURL=data:application/json;base64, 