import { vec3 } from 'gl-matrix';
import { utilities as csUtils, StackViewport } from '@cornerstonejs/core';
import { getBoundingBoxAroundShapeIJK, getBoundingBoxAroundShapeWorld, } from '../../../utilities/boundingBox';
import { triggerSegmentationDataModified } from '../../../stateManagement/segmentation/triggerSegmentationEvents';
import { getStrategyData } from './utils/getStrategyData';
import { isAxisAlignedRectangle } from '../../../utilities/rectangleROITool/isAxisAlignedRectangle';
import BrushStrategy from './BrushStrategy';
import { StrategyCallbacks } from '../../../enums';
import compositions from './compositions';
const { transformWorldToIndex } = csUtils;
const initializeRectangle = {
    [StrategyCallbacks.Initialize]: (operationData) => {
        const { points, imageVoxelManager, viewport, segmentationImageData, segmentationVoxelManager, } = operationData;
        if (!points) {
            return;
        }
        const center = vec3.fromValues(0, 0, 0);
        points.forEach((point) => {
            vec3.add(center, center, point);
        });
        vec3.scale(center, center, 1 / points.length);
        operationData.centerWorld = center;
        operationData.centerIJK = transformWorldToIndex(segmentationImageData, center);
        const { boundsIJK, pointInShapeFn } = createPointInRectangle(viewport, points, segmentationImageData);
        operationData.isInObject = pointInShapeFn;
        operationData.isInObjectBoundsIJK = boundsIJK;
    },
};
function createPointInRectangle(viewport, points, segmentationImageData) {
    let rectangleCornersIJK = points.map((world) => {
        return transformWorldToIndex(segmentationImageData, world);
    });
    rectangleCornersIJK = rectangleCornersIJK.map((point) => {
        return point.map((coord) => {
            return Math.round(coord);
        });
    });
    const boundsIJK = getBoundingBoxAroundShapeIJK(rectangleCornersIJK, segmentationImageData.getDimensions());
    const isStackViewport = viewport instanceof StackViewport;
    const isAligned = isStackViewport || isAxisAlignedRectangle(rectangleCornersIJK);
    const direction = segmentationImageData.getDirection();
    const spacing = segmentationImageData.getSpacing();
    const { viewPlaneNormal } = viewport.getCamera();
    const EPS = csUtils.getSpacingInNormalDirection({
        direction,
        spacing,
    }, viewPlaneNormal);
    const pointsBoundsLPS = getBoundingBoxAroundShapeWorld(points);
    let [[xMin, xMax], [yMin, yMax], [zMin, zMax]] = pointsBoundsLPS;
    xMin -= EPS;
    xMax += EPS;
    yMin -= EPS;
    yMax += EPS;
    zMin -= EPS;
    zMax += EPS;
    const pointInShapeFn = isAligned
        ? () => true
        : (pointLPS) => {
            const [x, y, z] = pointLPS;
            const xInside = x >= xMin && x <= xMax;
            const yInside = y >= yMin && y <= yMax;
            const zInside = z >= zMin && z <= zMax;
            return xInside && yInside && zInside;
        };
    return { boundsIJK, pointInShapeFn };
}
const RECTANGLE_STRATEGY = new BrushStrategy('Rectangle', compositions.regionFill, compositions.setValue, initializeRectangle, compositions.determineSegmentIndex, compositions.preview, compositions.labelmapStatistics);
const RECTANGLE_THRESHOLD_STRATEGY = new BrushStrategy('RectangleThreshold', compositions.regionFill, compositions.setValue, initializeRectangle, compositions.determineSegmentIndex, compositions.dynamicThreshold, compositions.threshold, compositions.preview, compositions.islandRemoval, compositions.labelmapStatistics);
const fillInsideRectangle = RECTANGLE_STRATEGY.strategyFunction;
const thresholdInsideRectangle = RECTANGLE_THRESHOLD_STRATEGY.strategyFunction;
export { RECTANGLE_STRATEGY, RECTANGLE_THRESHOLD_STRATEGY, fillInsideRectangle, thresholdInsideRectangle, };
