export class ShapeParser {
    static parse(obj, partShapes, prefix) {
        const stack = [obj];
        let index = 0;
        while (stack.length > 0) {
            const current = stack.pop();
            if (typeof current !== "object" || current === null) {
                continue; // Skip non-object values
            }
            if (Array.isArray(current)) {
                for (let i = 0; i < current.length; i++) {
                    stack.push(current[i]); // Push array elements onto the stack
                }
            }
            else {
                const keys = Object.keys(current);
                if (keys.includes("shapes")) {
                    const shapes = current.shapes;
                    if (typeof shapes === "object" && shapes !== null) {
                        for (const key in shapes) {
                            const sh = shapes[key];
                            if (sh) {
                                if (typeof shapes[key] !== "string") {
                                    let id;
                                    if (current.id) {
                                        id = `${prefix}-${current.id}-${key}-${index}`;
                                    }
                                    else {
                                        id = `${prefix}-${key}-${index}`;
                                    }
                                    partShapes.push({ id, shape: sh });
                                    shapes[key] = id;
                                }
                                index++;
                            }
                        }
                    }
                }
                for (const key in current) {
                    stack.push(current[key]); // Push object properties onto the stack
                }
            }
        }
        return obj;
    }
    static alignAndTranslateShapesWithChildren(part, transforms, rotation, direction, center, scale = [1, 1, 1]) {
        const partCloned = ShapeParser.deepCopy(part);
        partCloned.rotation = rotation;
        partCloned.direction = direction;
        partCloned.center = center;
        partCloned.scale = scale;
        if (partCloned.shapes) {
            Object.keys(partCloned.shapes).forEach(key => {
                const sh = partCloned.shapes[key];
                if (sh) {
                    const rotated = transforms.rotate({ shape: sh, angle: rotation, axis: [0, 1, 0] });
                    const aligned = transforms.alignAndTranslate({ shape: rotated, direction, center });
                    if (scale[0] !== 1 || scale[1] !== 1 || scale[2] !== 1) {
                        partCloned.shapes[key] = transforms.scale3d({ shape: aligned, scale, center });
                        aligned.delete();
                    }
                    else {
                        partCloned.shapes[key] = aligned;
                    }
                    rotated.delete();
                }
            });
        }
        Object.keys(partCloned).forEach(key => {
            const sh = partCloned[key];
            if (sh && Array.isArray(sh)) {
                partCloned[key] = sh.map((s) => {
                    if (s && typeof s === "object" && s !== null) {
                        if (s.shapes) {
                            const updatedShape = this.alignAndTranslateShapesWithChildren(s, transforms, rotation, direction, center, scale);
                            return updatedShape;
                        }
                        else {
                            return s;
                        }
                    }
                    else {
                        return s;
                    }
                });
            }
            else if (sh && typeof sh === "object" && sh !== null) {
                if (sh.shapes) {
                    partCloned[key] = this.alignAndTranslateShapesWithChildren(sh, transforms, rotation, direction, center, scale);
                }
            }
        });
        return partCloned;
    }
    static deleteAllShapes(part) {
        Object.keys(part.shapes).forEach(key => {
            part.shapes[key].delete();
        });
        Object.keys(part).forEach(key => {
            const sh = part[key];
            if (sh && Array.isArray(sh)) {
                sh.forEach((s) => {
                    if (s && typeof s === "object" && s !== null) {
                        if (s.shapes) {
                            this.deleteAllShapes(s);
                        }
                    }
                });
            }
            else if (sh && typeof sh === "object" && sh !== null) {
                if (sh.shapes) {
                    this.deleteAllShapes(sh);
                }
            }
        });
    }
    static deepCopy(part) {
        const clonedPart = Object.assign(Object.assign({}, part), { shapes: Object.assign({}, part.shapes) });
        Object.keys(part).forEach(key => {
            const sh = part[key];
            if (sh && typeof sh === "object" && sh !== null) {
                if (sh.shapes) {
                    clonedPart[key] = this.deepCopy(sh);
                }
            }
            else if (sh && Array.isArray(sh)) {
                clonedPart[key] = sh.map((s) => {
                    if (s && typeof s === "object" && s !== null) {
                        if (s.shapes) {
                            return this.deepCopy(s);
                        }
                    }
                    return s;
                });
            }
        });
        return clonedPart;
    }
}
