import classNames from 'classnames';
import React, { useCallback, useContext, useEffect, useRef, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { getAttribute, getBooleanAttribute, getNumericAttribute } from '../../../dom-utils';
import AnswerToolbar from '../../AnswerToolbar';
import { ExamContext } from '../../context/ExamContext';
import { QuestionContext } from '../../context/QuestionContext';
import RichTextAnswer from '../RichTextAnswer';
import { Score } from '../../shared/Score';
import { answerLengthInfoId, answerScoreId } from '../../../ids';
import AnswerLengthInfo from '../../shared/AnswerLengthInfo';
import { CommonExamContext } from '../../context/CommonExamContext';
import { answerBlurred, answerFocused, saveAnswer, selectAnswerVersion } from '../../../store/answers/actions';
const borderWidthPx = 2;
const TextAnswerInput = ({ element, className }) => {
    const type = getAttribute(element, 'type');
    const questionId = getNumericAttribute(element, 'question-id');
    const displayNumber = getAttribute(element, 'display-number');
    const maxScore = getNumericAttribute(element, 'max-score');
    const useLanguageOfInstruction = getBooleanAttribute(element, 'use-language-of-instruction');
    const maxLength = getNumericAttribute(element, 'max-length');
    const { language } = useContext(CommonExamContext);
    const { questionLabelIds, answers } = useContext(QuestionContext);
    const { examServerApi } = useContext(ExamContext);
    const [screenshotError, setScreenshotError] = useState();
    const answer = useSelector((state) => state.answers.answersById[questionId]);
    const supportsAnswerHistory = useSelector((state) => state.answers.supportsAnswerHistory);
    const showAnswerHistory = useSelector((state) => state.answers.supportsAnswerHistory && state.answers.serverQuestionIds.has(questionId));
    const validationError = useSelector((state) => state.answers.validationErrors.find((error) => error.type === 'AnswerTooLong' && error.displayNumber === displayNumber));
    const dispatch = useDispatch();
    const ref = useRef(null);
    const value = answer && answer.value;
    const scoreId = answerScoreId(element);
    const invalid = validationError != null;
    const lang = useLanguageOfInstruction ? language : undefined;
    const labelledBy = element.hasAttribute('max-length')
        ? `${questionLabelIds} ${answerLengthInfoId(element)}`
        : questionLabelIds;
    useEffect(() => {
        const { current } = ref;
        if (current) {
            if (type === 'single-line' || type === 'integer') {
                current.style.width = '0';
                current.style.width = `${current.scrollWidth + borderWidthPx}px`;
            }
        }
    });
    const onChange = useCallback(event => {
        const value = event.currentTarget.value.trim();
        const answer = {
            type: 'text',
            questionId,
            value,
            characterCount: getCharacterCount(value),
            displayNumber
        };
        dispatch(saveAnswer(answer));
        setScreenshotError(undefined);
    }, [questionId, displayNumber]);
    const [integerValue, setIntegerValue] = useState((answer === null || answer === void 0 ? void 0 : answer.value) || '');
    const onIntegerChange = useCallback(event => {
        event.preventDefault();
        event.currentTarget.classList.remove('text-answer--integer--input-error');
        const patternForIntegers = /^(\u002D|\u2212)?\d*$/;
        const value = event.currentTarget.value.trim();
        if (patternForIntegers.test(value)) {
            setIntegerValue(value);
            const answer = {
                type: 'text',
                questionId,
                value,
                characterCount: getCharacterCount(value),
                displayNumber
            };
            dispatch(saveAnswer(answer));
            setScreenshotError(undefined);
        }
        else {
            event.currentTarget.classList.add('text-answer--integer--input-error');
            setTimeout((target) => {
                target.classList.remove('text-answer--integer--input-error');
            }, 200, event.currentTarget);
        }
    }, [questionId, displayNumber]);
    const onRichTextChange = useCallback((answerHtml, answerText) => {
        const answer = {
            type: 'richText',
            questionId,
            value: answerHtml,
            characterCount: getCharacterCount(answerText),
            displayNumber
        };
        dispatch(saveAnswer(answer));
        setScreenshotError(undefined);
    }, [questionId, displayNumber]);
    const onError = useCallback((screenshotError) => setScreenshotError(screenshotError), [screenshotError]);
    const onFocus = useCallback(() => dispatch(answerFocused(questionId)), [questionId]);
    const onBlur = useCallback(() => dispatch(answerBlurred(questionId)), [questionId]);
    const wrappedSelectAnswerVersion = useCallback((questionId, questionText) => dispatch(selectAnswerVersion(questionId, questionText)), []);
    switch (type) {
        case 'rich-text':
            return (React.createElement(React.Fragment, null,
                maxLength != null && React.createElement(AnswerLengthInfo, { maxLength, id: answerLengthInfoId(element) }),
                React.createElement("div", { className: "text-answer-container" },
                    React.createElement(RichTextAnswer, { answer: answer, className: classNames('text-answer text-answer--rich-text', className), saveScreenshot: data => examServerApi.saveScreenshot(questionId, data), onChange: onRichTextChange, onError: onError, questionId: questionId, lang: lang, invalid: invalid, labelledBy: labelledBy }),
                    React.createElement(AnswerToolbar, { answer,
                        element,
                        selectAnswerVersion: wrappedSelectAnswerVersion,
                        showAnswerHistory,
                        supportsAnswerHistory,
                        screenshotError,
                        validationError }))));
        case 'integer':
            return (React.createElement("span", { className: "e-nowrap" },
                React.createElement("input", { type: "text", className: classNames('text-answer text-answer--single-line text-answer--integer', className), value: integerValue, onChange: onIntegerChange, onFocus: onFocus, onBlur: onBlur, spellCheck: "false", ref: ref, "data-question-id": questionId, lang: lang, "aria-describedby": scoreId, "aria-labelledby": labelledBy }),
                answers.length > 1 && React.createElement(Score, { score: maxScore, size: "inline", id: scoreId })));
        case 'single-line':
        default:
            return (React.createElement("span", { className: "e-nowrap" },
                React.createElement("input", { type: "text", className: classNames('text-answer text-answer--single-line', className), defaultValue: value, onChange: onChange, onFocus: onFocus, onBlur: onBlur, spellCheck: "false", ref: ref, "data-question-id": questionId, lang: lang, "aria-describedby": scoreId, "aria-labelledby": labelledBy }),
                answers.length > 1 && React.createElement(Score, { score: maxScore, size: "inline", id: scoreId })));
    }
};
export function getCharacterCount(answerText) {
    return answerText.replace(/\s/g, '').length;
}
export default React.memo(TextAnswerInput);
//# sourceMappingURL=TextAnswerInput.js.map