export class OCCTFillets {
    constructor(occ, och) {
        this.occ = occ;
        this.och = och;
    }
    filletEdges(inputs) {
        return this.och.filletsService.filletEdges(inputs);
    }
    filletEdgesList(inputs) {
        return this.och.filletsService.filletEdgesList(inputs);
    }
    filletEdgesListOneRadius(inputs) {
        return this.och.filletsService.filletEdgesListOneRadius(inputs);
    }
    filletEdgeVariableRadius(inputs) {
        return this.och.filletsService.filletEdgeVariableRadius(inputs);
    }
    filletEdgesVariableRadius(inputs) {
        return this.och.filletsService.filletEdgesVariableRadius(inputs);
    }
    filletEdgesSameVariableRadius(inputs) {
        return this.och.filletsService.filletEdgesSameVariableRadius(inputs);
    }
    chamferEdges(inputs) {
        return this.och.filletsService.chamferEdges(inputs);
    }
    chamferEdgesList(inputs) {
        return this.och.filletsService.chamferEdgesList(inputs);
    }
    chamferEdgeDistAngle(inputs) {
        return this.och.filletsService.chamferEdgeDistAngle(inputs);
    }
    chamferEdgesDistAngle(inputs) {
        return this.och.filletsService.chamferEdgesDistAngle(inputs);
    }
    chamferEdgesDistsAngles(inputs) {
        return this.och.filletsService.chamferEdgesDistsAngles(inputs);
    }
    chamferEdgeTwoDistances(inputs) {
        return this.och.filletsService.chamferEdgeTwoDistances(inputs);
    }
    chamferEdgesTwoDistances(inputs) {
        return this.och.filletsService.chamferEdgesTwoDistances(inputs);
    }
    chamferEdgesTwoDistancesLists(inputs) {
        return this.och.filletsService.chamferEdgesTwoDistancesLists(inputs);
    }
    filletTwoEdgesInPlaneIntoAWire(inputs) {
        const pln = this.och.entitiesService.gpPln(inputs.planeOrigin, inputs.planeDirection);
        const fil = new this.occ.ChFi2d_FilletAlgo_3(inputs.edge1, inputs.edge2, pln);
        fil.Perform(inputs.radius);
        const pt = this.och.entitiesService.gpPnt(inputs.planeOrigin);
        const edge1 = new this.occ.TopoDS_Edge();
        const edge2 = new this.occ.TopoDS_Edge();
        let solution = -1;
        if (inputs.solution !== undefined) {
            solution = inputs.solution;
        }
        const filletedEdge = fil.Result(pt, edge1, edge2, solution);
        const result = this.och.converterService.combineEdgesAndWiresIntoAWire({ shapes: [edge1, filletedEdge, edge2] });
        fil.delete();
        pt.delete();
        pln.delete();
        edge1.delete();
        edge2.delete();
        filletedEdge.delete();
        return result;
    }
    fillet3DWire(inputs) {
        return this.och.filletsService.fillet3DWire(inputs);
    }
    fillet2d(inputs) {
        if (inputs.indexes && inputs.radiusList && inputs.radiusList.length !== inputs.indexes.length) {
            throw new Error("When using radius list, length of the list must match index list of corners that you want to fillet.");
        }
        let face;
        let isShapeFace = false;
        if (inputs.shape.ShapeType() === this.occ.TopAbs_ShapeEnum.TopAbs_FACE) {
            face = this.och.converterService.getActualTypeOfShape(inputs.shape);
            isShapeFace = true;
        }
        else if (inputs.shape.ShapeType() === this.occ.TopAbs_ShapeEnum.TopAbs_WIRE) {
            const faceBuilder = new this.occ.BRepBuilderAPI_MakeFace_15(inputs.shape, true);
            const messageProgress = new this.occ.Message_ProgressRange_1();
            faceBuilder.Build(messageProgress);
            const shape = faceBuilder.Shape();
            face = this.och.converterService.getActualTypeOfShape(shape);
            shape.delete();
            messageProgress.delete();
            faceBuilder.delete();
        }
        else {
            throw new Error("You can only fillet a 2d wire or a 2d face.");
        }
        const filletMaker = new this.occ.BRepFilletAPI_MakeFillet2d_2(face);
        const anVertexExplorer = new this.occ.TopExp_Explorer_2(inputs.shape, this.occ.TopAbs_ShapeEnum.TopAbs_VERTEX, this.occ.TopAbs_ShapeEnum.TopAbs_SHAPE);
        let i = 1;
        const cornerVertices = [];
        for (anVertexExplorer; anVertexExplorer.More(); anVertexExplorer.Next()) {
            const vertex = this.occ.TopoDS.Vertex_1(anVertexExplorer.Current());
            if (i % 2 === 0) {
                cornerVertices.push(vertex);
            }
            i++;
        }
        if (!isShapeFace) {
            const wire = inputs.shape;
            if (!wire.Closed_1()) {
                cornerVertices.pop();
            }
        }
        let radiusAddedCounter = 0;
        cornerVertices.forEach((cvx, index) => {
            if (!inputs.indexes) {
                this.applyRadiusToVertex(inputs, filletMaker, cvx, index);
            }
            else if (inputs.indexes.includes(index + 1)) {
                this.applyRadiusToVertex(inputs, filletMaker, cvx, radiusAddedCounter);
                radiusAddedCounter++;
            }
        });
        const messageProgress = new this.occ.Message_ProgressRange_1();
        filletMaker.Build(messageProgress);
        let result;
        if (isShapeFace) {
            result = filletMaker.Shape();
        }
        else {
            const isDone = filletMaker.IsDone();
            if (isDone) {
                const shape = filletMaker.Shape();
                const filletedWires = this.och.shapeGettersService.getWires({ shape });
                if (filletedWires.length === 1) {
                    result = filletedWires[0];
                }
            }
            else {
                // Previous algorithm fails if the wire is not made up of circular or straight edges. This algorithm is a failover.
                const normal = this.och.facesService.faceNormalOnUV({ shape: face, paramU: 0.5, paramV: 0.5 });
                result = this.fillet3DWire({ shape: inputs.shape, radius: inputs.radius, radiusList: inputs.radiusList, indexes: inputs.indexes, direction: normal });
            }
        }
        anVertexExplorer.delete();
        filletMaker.delete();
        messageProgress.delete();
        cornerVertices.forEach(cvx => cvx.delete());
        return result;
    }
    applyRadiusToVertex(inputs, filletMaker, cvx, index) {
        if (inputs.radiusList) {
            const radiusList = inputs.radiusList;
            filletMaker.AddFillet(cvx, radiusList[index]);
        }
        else if (inputs.radius) {
            filletMaker.AddFillet(cvx, inputs.radius);
        }
    }
}
