import * as Inputs from "../../api/inputs/inputs";
export class VerticesService {
    constructor(occ, entitiesService, converterService, shapeGettersService, wiresService, booleansService) {
        this.occ = occ;
        this.entitiesService = entitiesService;
        this.converterService = converterService;
        this.shapeGettersService = shapeGettersService;
        this.wiresService = wiresService;
        this.booleansService = booleansService;
    }
    vertexFromXYZ(inputs) {
        return this.entitiesService.makeVertex([inputs.x, inputs.y, inputs.z]);
    }
    vertexFromPoint(inputs) {
        return this.entitiesService.makeVertex(inputs.point);
    }
    verticesFromPoints(inputs) {
        return inputs.points.map(p => this.vertexFromPoint({ point: p }));
    }
    verticesCompoundFromPoints(inputs) {
        const vertexes = this.verticesFromPoints(inputs);
        return this.converterService.makeCompound({ shapes: vertexes });
    }
    getVertices(inputs) {
        return this.shapeGettersService.getVertices(inputs);
    }
    getVerticesAsPoints(inputs) {
        const vertices = this.shapeGettersService.getVertices(inputs);
        return this.verticesToPoints({ shapes: vertices });
    }
    verticesToPoints(inputs) {
        return inputs.shapes.map(v => {
            const pt = this.occ.BRep_Tool.Pnt(v);
            const res = [pt.X(), pt.Y(), pt.Z()];
            pt.delete();
            return res;
        });
    }
    pointsToVertices(inputs) {
        return inputs.shapes.map(v => {
            const pt = this.occ.BRep_Tool.Pnt(v);
            const res = [pt.X(), pt.Y(), pt.Z()];
            pt.delete();
            return res;
        });
    }
    vertexToPoint(inputs) {
        return this.converterService.vertexToPoint(inputs);
    }
    projectPoints(inputs) {
        const pointsAlongDir = inputs.points.map(p => [p[0] + inputs.direction[0], p[1] + inputs.direction[1], p[2] + inputs.direction[2]]);
        const lines = pointsAlongDir.map((p, i) => ({
            start: inputs.points[i],
            end: p
        }));
        const wiresFromPoints = this.wiresService.createLines({ lines, returnCompound: false });
        const allPoints = wiresFromPoints.map((wire, index) => {
            const x = this.booleansService.intersection({
                shapes: [wire, inputs.shape],
                keepEdges: false
            });
            const res = x.map(s => {
                return this.shapeGettersService.getVertices({ shape: s });
            });
            if (res) {
                const pts = this.verticesToPoints({ shapes: res.flat().filter(s => s !== undefined) });
                if (inputs.projectionType === Inputs.OCCT.pointProjectionTypeEnum.closest) {
                    return [this.getClosestPointFromPoints(pts, inputs.points[index])];
                }
                else if (inputs.projectionType === Inputs.OCCT.pointProjectionTypeEnum.furthest) {
                    return [this.getFurthestPointFromPoints(pts, inputs.points[index])];
                }
                else if (inputs.projectionType === Inputs.OCCT.pointProjectionTypeEnum.closestAndFurthest) {
                    return [this.getClosestPointFromPoints(pts, inputs.points[index]), this.getFurthestPointFromPoints(pts, inputs.points[index])];
                }
                else if (inputs.projectionType === Inputs.OCCT.pointProjectionTypeEnum.all) {
                    return pts;
                }
                else {
                    return undefined;
                }
            }
            else {
                return undefined;
            }
        });
        const points = allPoints.flat().filter(s => s !== undefined);
        return points;
    }
    getClosestPointFromPoints(points, point) {
        let minDist = Number.MAX_VALUE;
        let closestPoint = [0, 0, 0];
        points.forEach(p => {
            const dist = this.distanceBetweenTwoPoints(point, p);
            if (dist < minDist) {
                minDist = dist;
                closestPoint = p;
            }
        });
        return closestPoint;
    }
    getFurthestPointFromPoints(points, point) {
        let maxDist = 0;
        let furthestPoint = [0, 0, 0];
        points.forEach(p => {
            const dist = this.distanceBetweenTwoPoints(point, p);
            if (dist > maxDist) {
                maxDist = dist;
                furthestPoint = p;
            }
        });
        return furthestPoint;
    }
    distanceBetweenTwoPoints(p1, p2) {
        const x = p2[0] - p1[0];
        const y = p2[1] - p1[1];
        const z = p2[2] - p1[2];
        return Math.sqrt(x * x + y * y + z * z);
    }
}
