"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createTmpIdTree = createTmpIdTree;
const utils_1 = require("../utils");
class IdService {
    constructor(schema, formData) {
        this.getUUID = (item) => item ? (item.id || item._lajiFormId) : undefined;
        this.tmpIdTree = createTmpIdTree(schema);
        this.formData = formData;
    }
    setSchema(schema) {
        this.tmpIdTree = createTmpIdTree(schema);
    }
    setFormData(formData) {
        this.formData = formData;
    }
    addLajiFormIds(formData, immutably = true) {
        return (0, utils_1.addLajiFormIds)(formData, this.tmpIdTree, immutably);
    }
    getAllLajiFormIdsDeeply(formData) {
        return (0, utils_1.getAllLajiFormIdsDeeply)(formData, this.tmpIdTree);
    }
    removeLajiFormIds(formData) {
        return (0, utils_1.removeLajiFormIds)(formData, this.tmpIdTree);
    }
    findPointerForLajiFormId(tmpIdTree = {}, formData, lajiFormId) {
        if (tmpIdTree._hasId) {
            if (Array.isArray(formData)) {
                for (let idx in (formData || [])) {
                    const item = formData[idx];
                    if (this.getUUID(item) === lajiFormId) {
                        return "/" + idx;
                    }
                }
            }
            else if (formData && this.getUUID(formData) === lajiFormId) {
                return "";
            }
        }
        for (const k of Object.keys(tmpIdTree)) {
            if ((0, utils_1.isObject)(formData[k])) {
                const find = this.findPointerForLajiFormId(tmpIdTree[k], formData[k], lajiFormId);
                if (find !== undefined || find === "") {
                    return `/${k}${find}`;
                }
            }
            else if (Array.isArray(formData[k])) {
                for (const i in formData[k]) {
                    const item = formData[k][i];
                    const find = this.findPointerForLajiFormId(tmpIdTree[k], item, lajiFormId);
                    if (find !== undefined || find === "") {
                        return `/${k}/${i}${find}`;
                    }
                }
            }
        }
        return undefined;
    }
    getJSONPointerFromLajiFormIdAndRelativePointer(lajiFormId, relativePointer) {
        const containerPointer = this.findPointerForLajiFormId(this.tmpIdTree, this.formData, lajiFormId);
        if (!containerPointer) {
            return "";
        }
        return containerPointer + relativePointer;
    }
    getJSONPointerFromLajiFormIdAndFormDataAndIdSchemaId(idSchemaId, lajiFormId) {
        const relativePointer = this.getRelativePointer(idSchemaId, lajiFormId);
        return this.getJSONPointerFromLajiFormIdAndRelativePointer(lajiFormId, relativePointer || "");
    }
    getRelativePointer(idSchemaId, lajiFormId) {
        var _a;
        const containerPointer = this.findPointerForLajiFormId(this.tmpIdTree, this.formData, lajiFormId);
        if (!containerPointer) {
            return "";
        }
        const indicesCount = ((_a = containerPointer.match(/\/[0-9]+/g)) === null || _a === void 0 ? void 0 : _a.length) || 0;
        const containerPointerWithoutArrayIndices = containerPointer.replace(/[0-9]+/g, "");
        const thisPointer = idSchemaId.replace("root", "").replace(/_/g, "/");
        let thisPointerWithoutContainerIndices = thisPointer;
        for (let i = indicesCount; i > 0; i--) {
            thisPointerWithoutContainerIndices = thisPointerWithoutContainerIndices.replace(/[0-9]+/, "");
        }
        return thisPointerWithoutContainerIndices.replace(containerPointerWithoutArrayIndices, "");
    }
    getRelativeTmpIdTree(id) {
        let tmpIdTree = this.tmpIdTree;
        if (!tmpIdTree) {
            return undefined;
        }
        const treePath = id.replace(/root|_[0-9]+|_/g, "_").split("_").filter(i => i);
        for (const k of treePath) {
            if (tmpIdTree[k]) {
                tmpIdTree = tmpIdTree[k];
            }
            else {
                tmpIdTree = undefined;
                break;
            }
        }
        return tmpIdTree;
    }
}
exports.default = IdService;
function createTmpIdTree(schema) {
    function walk(_schema) {
        if (_schema.properties) {
            const _walked = Object.keys(_schema.properties).reduce((paths, key) => {
                const walked = walk(_schema.properties[key]);
                if (walked) {
                    paths[key] = walked;
                }
                return paths;
            }, {});
            if (Object.keys(_walked).length)
                return _walked;
        }
        else if (_schema.type === "array" && _schema.items.type === "object") {
            return Object.keys(_schema.items.properties).reduce((paths, key) => {
                const walked = walk(_schema.items.properties[key]);
                if (walked) {
                    paths[key] = walked;
                }
                return paths;
            }, { _hasId: true });
        }
        return undefined;
    }
    return walk(schema);
}
