import React, { useEffect, useLayoutEffect, useRef, useState } from 'react';
import { I18nextProvider } from 'react-i18next';
import { changeLanguage, initI18n, useExamTranslation } from '../../i18n';
import { renderAnnotations, renderImageAnnotationByImage, updateImageAnnotationMarkSize } from '../../renderAnnotations';
import { useCached } from '../../useCached';
import { AnswerCharacterCounter } from './AnswerCharacterCounter';
import { annotationFromMousePosition, getOverlappingMessages, hasTextSelectedInAnswerText, imageAnnotationMouseDownInfo, isDesktopVersion, mergeAnnotation, preventDefaults, showAndPositionElement, textAnnotationFromRange, toggle } from './editAnnotations';
import GradingAnswerAnnotationList from './GradingAnswerAnnotationList';
import { updateLargeImageWarnings } from './largeImageDetector';
import AudioPlayer from '../shared/internal/AudioPlayer';
import { wrapAllImages } from '../../dom-utils';
export function GradingAnswer(props) {
    const i18n = useCached(() => initI18n(props.language));
    useEffect(changeLanguage(i18n, props.language));
    return (React.createElement(I18nextProvider, { i18n: i18n },
        React.createElement(GradingAnswerWithTranslations, { ...props })));
}
function GradingAnswerWithTranslations({ answer: { type, characterCount, value }, language, isReadOnly, gradingRole, annotations, saveAnnotations, maxLength, popupTopMargin = 25 }) {
    const answerRef = useRef(null);
    const popupRef = useRef(null);
    const messageRef = useRef(null);
    const tooltipRef = useRef(null);
    let newAnnotationObject;
    let savedAnnotations;
    const imgAnnotationState = { start: undefined, element: undefined, img: undefined };
    let isEditAnnotationPopupVisible = false;
    let annotationDataForTooltip;
    let annotationPositionForPopup;
    let hideTooltipTimeout;
    let windowResizeTimeout;
    let selectionChangeTimeout;
    const [loadedCount, setLoadedCount] = useState(0);
    const [totalImages, setTotalImages] = useState(0);
    const [failedImages, setFailedImages] = useState(0);
    useEffect(() => {
        const nonEmptyImages = Array.from(document.querySelectorAll('.e-grading-answer img[src]')).filter(e => !e.src.endsWith('/math.svg?latex='));
        function handleImageLoaded() {
            setLoadedCount(prevCount => prevCount + 1);
        }
        function handleImageError(img) {
            console.error('Image failed to load:', img.src);
            setFailedImages(prevCount => prevCount + 1);
            img.alt = 'Image failed to load';
            img.style.border = '1px solid red';
        }
        setTotalImages((nonEmptyImages === null || nonEmptyImages === void 0 ? void 0 : nonEmptyImages.length) || 0);
        setLoadedCount(0);
        setFailedImages(0);
        nonEmptyImages === null || nonEmptyImages === void 0 ? void 0 : nonEmptyImages.forEach(img => {
            if (img instanceof HTMLImageElement) {
                if (img.complete) {
                    if (!img.naturalWidth || !img.naturalHeight) {
                        handleImageError(img);
                    }
                    else {
                        handleImageLoaded();
                    }
                }
                else {
                    img.addEventListener('load', handleImageLoaded);
                    img.addEventListener('error', () => handleImageError(img));
                }
            }
        });
        return () => {
            nonEmptyImages === null || nonEmptyImages === void 0 ? void 0 : nonEmptyImages.forEach(img => {
                if (img instanceof HTMLImageElement) {
                    img.removeEventListener('load', handleImageLoaded);
                    img.removeEventListener('error', () => handleImageError(img));
                }
            });
        };
    }, [value]);
    useLayoutEffect(() => {
        if (answerRef.current && tooltipRef.current && popupRef.current) {
            savedAnnotations = annotations;
            toggle(tooltipRef.current, false);
            toggle(popupRef.current, false);
            renderAnswerWithAnnotations(savedAnnotations);
            answerRef.current.setAttribute('lang', language);
            document.addEventListener('selectionchange', onSelectionChangeForMobileDevices);
        }
        window.onresize = () => {
            clearTimeout(windowResizeTimeout);
            windowResizeTimeout = setTimeout(() => updateLargeImageWarnings(answerRef.current), 1000);
        };
        return () => {
            window.removeEventListener('keydown', onKeyUpInAnnotationPopup);
            window.removeEventListener('mouseup', onWindowMouseUpAfterAnswerMouseDown);
            window.removeEventListener('mousemove', onMouseMoveForImageAnnotation);
        };
    });
    const { t } = useExamTranslation();
    const allImagesNotLoaded = totalImages > 0 && loadedCount !== totalImages;
    const someImagesFailedToLoad = failedImages > 0;
    return (React.createElement("div", { onClick: e => onAnnotationOrListClick(e), className: "e-grading-answer-wrapper" },
        allImagesNotLoaded && (React.createElement("div", { className: "loading-images" },
            React.createElement("span", { className: "loading" },
                t('grading.loading-images'),
                " (",
                loadedCount,
                "/",
                totalImages,
                ")"),
            someImagesFailedToLoad && React.createElement("span", { className: "failed" }, t('grading.some-images-failed')))),
        type == 'audio' ? (React.createElement("div", { className: "e-grading-answer e-line-height-l e-mrg-b-1" }, value && React.createElement(AudioPlayer, { variant: "recorded", src: value }))) : (React.createElement(React.Fragment, null,
            React.createElement("div", { className: "e-grading-answer e-line-height-l e-mrg-b-1", ref: answerRef, onMouseDown: e => onAnswerMouseDown(e), onMouseOver: e => onMouseOverAnnotation(e.target) }),
            React.createElement(AnswerCharacterCounter, { characterCount: characterCount, maxLength: maxLength }))),
        React.createElement(GradingAnswerAnnotationList, { censoring: annotations.censoring, pregrading: annotations.pregrading, singleGrading: gradingRole === 'pregrading' }),
        React.createElement("form", { style: { display: 'none' }, ref: popupRef, className: "e-grading-answer-popup e-grading-answer-add-annotation", onSubmit: e => onSubmitAnnotation(e) },
            React.createElement("input", { onFocus: () => onNewAnnotationMessageFocus(), name: "message", className: "e-grading-answer-add-annotation-text", type: "text", ref: messageRef }),
            React.createElement("button", { className: "e-grading-answer-add-annotation-button", type: "submit", "data-i18n": "arpa.annotate" }, t('grading.annotate')),
            React.createElement("button", { className: "e-grading-answer-close-popup", onClick: e => {
                    e.preventDefault();
                    hideAnnotationPopupAndRefresh();
                } }, "\u00D7")),
        React.createElement("div", { style: { display: 'none' }, ref: tooltipRef, className: "e-grading-answer-tooltip e-grading-answer-popup", onMouseOver: onMouseOverTooltip, onMouseOut: hideTooltip },
            React.createElement("span", { onClick: e => editExistingAnnotation(e), className: "e-grading-answer-tooltip-label" }),
            React.createElement("button", { onClick: e => removeAnnotation(e), className: "e-grading-answer-tooltip-remove" }, "\u00D7"))));
    function onAnnotationOrListClick(e) {
        var _a;
        const element = e.target;
        if (element instanceof HTMLElement) {
            if (element.tagName === 'MARK') {
                if (!imgAnnotationState.element) {
                    showTooltip(element);
                }
            }
            else if (element.tagName === 'LI') {
                const index = (_a = element.dataset.listNumber) === null || _a === void 0 ? void 0 : _a.replace(')', '');
                const mark = document.querySelector(`.e-annotation[data-index="${index}"]`);
                showTooltip(mark);
                mark.scrollIntoView({ block: 'center', behavior: 'smooth' });
            }
            else if (annotationDataForTooltip) {
                hideTooltip();
            }
        }
    }
    function editExistingAnnotation(e) {
        if (e.target.closest('.editable')) {
            toggle(tooltipRef.current, false);
            showExistingAnnotationPopup(annotationPositionForPopup);
        }
    }
    function removeAnnotation(e) {
        e.preventDefault();
        hideTooltip();
        savedAnnotations[annotationDataForTooltip.role].splice(annotationDataForTooltip.index, 1);
        annotationDataForTooltip = undefined;
        saveAnnotations(savedAnnotations);
    }
    function hideTooltip() {
        hideTooltipTimeout = setTimeout(() => {
            toggle(tooltipRef.current, false);
        }, 400);
    }
    function onMouseOverTooltip() {
        clearTimeout(hideTooltipTimeout);
    }
    function onMouseOutFromTooltip(e) {
        const target = e.target;
        if (target.tagName === 'MARK') {
            clearTimeout(hideTooltipTimeout);
            hideTooltip();
        }
        answerRef.current.removeEventListener('mouseout', onMouseOutFromTooltip);
    }
    function showTooltip(target) {
        if (isEditAnnotationPopupVisible) {
            return;
        }
        clearTimeout(hideTooltipTimeout);
        const tooltip = tooltipRef.current;
        const { type, listIndex, message } = target.dataset;
        tooltip.classList.toggle('editable', !isReadOnly && type === gradingRole);
        annotationPositionForPopup = target.getBoundingClientRect();
        showAndPositionElement(annotationPositionForPopup, answerRef.current, tooltip, popupTopMargin);
        tooltip.querySelector('.e-grading-answer-tooltip-label').textContent = message || '–';
        annotationDataForTooltip = { index: Number(listIndex), role: type, message: message || '' };
        answerRef.current.addEventListener('mouseout', onMouseOutFromTooltip);
    }
    function onMouseOverAnnotation(target) {
        const markElement = target.closest('mark');
        if (markElement &&
            !isEditAnnotationPopupVisible &&
            (!hasTextSelectedInAnswerText() || isReadOnly) &&
            !imgAnnotationState.element) {
            showTooltip(markElement);
        }
    }
    function showAnnotationPopup(rect, message) {
        annotationDataForTooltip = undefined;
        setupAnnotationPopup(rect, message);
    }
    function showExistingAnnotationPopup(rect) {
        setupAnnotationPopup(rect, annotationDataForTooltip.message);
    }
    function setupAnnotationPopup(rect, message) {
        // Could be active from previous popup
        window.removeEventListener('keydown', onKeyUpInAnnotationPopup);
        showAndPositionElement(rect, answerRef.current, popupRef.current, popupTopMargin);
        const inputElement = messageRef.current;
        inputElement.value = message;
        inputElement.focus();
        isEditAnnotationPopupVisible = true;
        window.addEventListener('keydown', onKeyUpInAnnotationPopup);
    }
    function hideAnnotationPopupAndRefresh() {
        newAnnotationObject = undefined;
        imgAnnotationState.element = undefined;
        imgAnnotationState.img = undefined;
        isEditAnnotationPopupVisible = false;
        window.removeEventListener('keydown', onKeyUpInAnnotationPopup);
        toggle(popupRef.current, false);
        renderAnswerWithAnnotations(savedAnnotations);
    }
    function onAnswerMouseDown(e) {
        var _a;
        // Do annotations only with left mouse buttons and when permitted
        if (isReadOnly || e.button !== 0) {
            return;
        }
        window.addEventListener('mouseup', onWindowMouseUpAfterAnswerMouseDown);
        const target = e.target;
        const img = ((_a = target.closest('.e-image-wrapper')) === null || _a === void 0 ? void 0 : _a.querySelector('img')) || undefined;
        if (!img) {
            return;
        }
        img.addEventListener('dragstart', preventDefaults); // Prevent dragging images when marking image annotations
        imgAnnotationState.start = imageAnnotationMouseDownInfo(e, img);
        imgAnnotationState.img = img;
        window.addEventListener('mousemove', onMouseMoveForImageAnnotation);
    }
    function onWindowMouseUpAfterAnswerMouseDown() {
        var _a, _b;
        (_a = imgAnnotationState.img) === null || _a === void 0 ? void 0 : _a.removeEventListener('dragstart', preventDefaults);
        window.removeEventListener('mousemove', onMouseMoveForImageAnnotation);
        window.removeEventListener('mouseup', onWindowMouseUpAfterAnswerMouseDown);
        // Image annotation is being created since shape exists
        if (imgAnnotationState.element) {
            showAnnotationPopup((_b = imgAnnotationState.element) === null || _b === void 0 ? void 0 : _b.getBoundingClientRect(), '');
            return;
        }
        // Text annotation
        const selection = window.getSelection();
        if (selection && answerRef.current !== null && hasTextSelectedInAnswerText()) {
            const range = selection.getRangeAt(0);
            const position = textAnnotationFromRange(answerRef.current, range);
            if (!position) {
                return;
            }
            const message = getOverlappingMessages(savedAnnotations[gradingRole], position.startIndex, position.length);
            newAnnotationObject = { ...position, type: 'text', message };
            showAnnotationPopup(range.getBoundingClientRect(), message);
            const newAnnotations = { ...savedAnnotations };
            newAnnotations[gradingRole] = mergeAnnotation(answerRef.current, newAnnotationObject, savedAnnotations[gradingRole]);
            renderAnswerWithAnnotations(newAnnotations);
        }
    }
    // Only used for touch devices
    function onNewAnnotationMessageFocus() {
        if (isDesktopVersion()) {
            return;
        }
        if (answerRef.current) {
            const newAnnotations = { ...savedAnnotations };
            newAnnotations[gradingRole] = mergeAnnotation(answerRef.current, newAnnotationObject, savedAnnotations[gradingRole]);
            renderAnswerWithAnnotations(newAnnotations);
        }
    }
    function onSelectionChangeForMobileDevices() {
        if (isDesktopVersion()) {
            return;
        }
        clearTimeout(selectionChangeTimeout);
        selectionChangeTimeout = setTimeout(onSelectionChangeAfterThrottle, 500);
    }
    function onSelectionChangeAfterThrottle() {
        const selection = window.getSelection();
        if (selection && answerRef.current !== null && hasTextSelectedInAnswerText()) {
            const range = selection.getRangeAt(0);
            const position = textAnnotationFromRange(answerRef.current, range);
            if (!position) {
                return;
            }
            const message = getOverlappingMessages(savedAnnotations[gradingRole], position.startIndex, position.length);
            isEditAnnotationPopupVisible = true;
            const inputElement = messageRef.current;
            inputElement.value = message;
            showAndPositionElement(range.getBoundingClientRect(), answerRef.current, popupRef.current, popupTopMargin);
            newAnnotationObject = { ...position, type: 'text', message };
        }
    }
    function onMouseMoveForImageAnnotation(e) {
        preventDefaults(e);
        newAnnotationObject = annotationFromMousePosition(e, imgAnnotationState.start);
        // Create shape on first mouse move and resize after that
        if (imgAnnotationState.element) {
            updateImageAnnotationMarkSize(imgAnnotationState.element, newAnnotationObject);
        }
        else {
            imgAnnotationState.element = renderImageAnnotationByImage(imgAnnotationState.img, '', newAnnotationObject, gradingRole, 999);
        }
    }
    function renderAnswerWithAnnotations(annotations) {
        const container = answerRef.current;
        if (type === 'richText') {
            container.innerHTML = value;
            wrapAllImages(container);
            updateLargeImageWarnings(container);
        }
        else if (type != 'audio') {
            container.textContent = value;
        }
        renderAnnotations(container, annotations.pregrading, annotations.censoring, false);
    }
    function onSubmitAnnotation(e) {
        e.preventDefault();
        const message = messageRef.current.value;
        if (annotationDataForTooltip) {
            // Editing existing annotation message by clicking tooltip
            savedAnnotations[annotationDataForTooltip.role][annotationDataForTooltip.index].message = message;
        }
        else {
            // Saving new annotation
            savedAnnotations[gradingRole] = mergeAnnotation(answerRef.current, { ...newAnnotationObject, message }, savedAnnotations[gradingRole] || []);
        }
        toggle(popupRef.current, false);
        saveAnnotations(savedAnnotations);
    }
    function onKeyUpInAnnotationPopup(e) {
        if (e.key === 'Escape' && isEditAnnotationPopupVisible) {
            e.stopPropagation();
            hideAnnotationPopupAndRefresh();
        }
    }
}
//# sourceMappingURL=GradingAnswer.js.map