import { utilities, BaseVolumeViewport, StackViewport, cache, metaData, } from '@cornerstonejs/core';
import { addAnnotation } from '../stateManagement/annotation/annotationState';
import { vec3 } from 'gl-matrix';
function annotationHydration(viewport, toolName, worldPoints, options) {
    const viewReference = viewport.getViewReference();
    const { viewPlaneNormal, FrameOfReferenceUID } = viewReference;
    const annotation = {
        annotationUID: options?.annotationUID || utilities.uuidv4(),
        data: {
            handles: {
                points: worldPoints,
            },
        },
        highlighted: false,
        autoGenerated: false,
        invalidated: false,
        isLocked: false,
        isVisible: true,
        metadata: {
            toolName,
            viewPlaneNormal,
            FrameOfReferenceUID,
            referencedImageId: getReferencedImageId(viewport, worldPoints[0], viewPlaneNormal),
            ...options,
        },
    };
    addAnnotation(annotation, viewport.element);
    return annotation;
}
function getReferencedImageId(viewport, worldPos, viewPlaneNormal) {
    let referencedImageId;
    if (viewport instanceof StackViewport) {
        referencedImageId = getClosestImageIdForStackViewport(viewport, worldPos, viewPlaneNormal);
    }
    else if (viewport instanceof BaseVolumeViewport) {
        const targetId = getTargetId(viewport);
        const volumeId = utilities.getVolumeId(targetId);
        const imageVolume = cache.getVolume(volumeId);
        referencedImageId = utilities.getClosestImageId(imageVolume, worldPos, viewPlaneNormal);
    }
    else {
        throw new Error('getReferencedImageId: viewport must be a StackViewport or BaseVolumeViewport');
    }
    return referencedImageId;
}
function getTargetId(viewport) {
    const targetId = viewport.getViewReferenceId?.();
    if (targetId) {
        return targetId;
    }
    if (viewport instanceof BaseVolumeViewport) {
        return `volumeId:${getTargetVolumeId(viewport)}`;
    }
    throw new Error('getTargetId: viewport must have a getTargetId method');
}
function getTargetVolumeId(viewport) {
    const actorEntries = viewport.getActors();
    if (!actorEntries) {
        return;
    }
    return actorEntries.find((actorEntry) => actorEntry.actor.getClassName() === 'vtkVolume')?.uid;
}
function getClosestImageIdForStackViewport(viewport, worldPos, viewPlaneNormal) {
    const imageIds = viewport.getImageIds();
    if (!imageIds || !imageIds.length) {
        return;
    }
    const distanceImagePairs = imageIds.map((imageId) => {
        const { imagePositionPatient } = metaData.get('imagePlaneModule', imageId);
        const distance = calculateDistanceToImage(worldPos, imagePositionPatient, viewPlaneNormal);
        return { imageId, distance };
    });
    distanceImagePairs.sort((a, b) => a.distance - b.distance);
    return distanceImagePairs[0].imageId;
}
function calculateDistanceToImage(worldPos, ImagePositionPatient, viewPlaneNormal) {
    const dir = vec3.create();
    vec3.sub(dir, worldPos, ImagePositionPatient);
    const dot = vec3.dot(dir, viewPlaneNormal);
    return Math.abs(dot);
}
export { annotationHydration, getClosestImageIdForStackViewport };
