import axios from 'axios';
import React from 'react';
import { UndoHistoryEntry } from './UndoHistoryEntry';
import ModalDialog from '../shared/internal/ModalDialog';
import { useExamTranslation } from '../../i18n';
const CancelToken = axios.CancelToken;
function toAnswerHistoryEntry(answer) {
    return {
        type: answer.type,
        value: answer.value,
        answerTime: answer.answer_time,
        characterCount: answer.character_count
    };
}
function AnswerDisplay(props) {
    const { selectedAnswer } = props;
    return selectedAnswer ? (selectedAnswer.type === 'richText' ? (React.createElement("div", { className: "e-undo-view-answer-content js-undo-answer-detail", dangerouslySetInnerHTML: { __html: selectedAnswer.value } })) : (React.createElement("div", { className: "e-undo-view-answer-content js-undo-answer-detail plainText" }, selectedAnswer.value))) : null;
}
function BottomBar(props) {
    const { selectedAnswer, selectedAnswerIndex, restoreAnswer, questionId } = props;
    const disableRestoreButton = !selectedAnswer || selectedAnswerIndex === 0;
    return (React.createElement("div", { className: "e-undo-view-bottom-bar" },
        React.createElement("button", { className: "e-button-default e-button js-restore-answer-button", disabled: disableRestoreButton, onClick: () => selectedAnswer && restoreAnswer({ ...selectedAnswer, questionId }) },
            React.createElement(RestoreButtonLabel, null))));
}
function escapedHtml(html) {
    const container = document.createElement('div');
    container.innerHTML = html;
    return container.innerText;
}
function getAnswerText(answer) {
    const fullText = answer.type === 'text' ? answer.value : escapedHtml(answer.value);
    return fullText.replace(/\s+/g, ' ').trim();
}
function truncateAnswer(answer, length = 50) {
    const answerText = getAnswerText(answer);
    if (answerText.length <= length) {
        return answerText;
    }
    const separator = '…';
    const charsToShow = length - separator.length;
    const startChars = Math.ceil(charsToShow / 2);
    const endChars = charsToShow - startChars;
    return answerText.substr(0, startChars) + separator + answerText.substr(answerText.length - endChars);
}
function countCharacters(answer) {
    const text = getAnswerText(answer);
    return text.replace(/\s/g, '').length;
}
function countScreenshots(answer) {
    const answerElement = document.createElement('div');
    answerElement.innerHTML = answer.value;
    const equationImageSelector = 'img[src^="/math.svg"], img[src^="data:image/svg+xml"]';
    const imageCount = answerElement.querySelectorAll('img').length;
    const emptyImageCount = answerElement.querySelectorAll('img[src=""]').length;
    const equationCount = answerElement.querySelectorAll(equationImageSelector).length;
    return imageCount - equationCount - emptyImageCount;
}
export class UndoView extends React.PureComponent {
    constructor(props) {
        super(props);
        this.source = CancelToken.source();
        this.keydownListener = (event) => {
            if (event.keyCode === 13) {
                const selectedAnswer = this.state.answers[this.state.selectedAnswerIndex];
                this.props.restoreAnswer({ ...selectedAnswer, questionId: this.props.questionId });
                this.close();
            }
        };
        this.state = {
            answers: [],
            selectedAnswerIndex: 0,
            loading: true,
            loadRetryTimeout: null
        };
    }
    componentDidMount() {
        document.addEventListener('keydown', this.keydownListener, false);
        void this.fetchAnswerHistory(this.props.questionId);
    }
    componentWillUnmount() {
        this.source.cancel();
        document.removeEventListener('keydown', this.keydownListener, false);
    }
    componentDidUpdate(prevProps) {
        if (this.props.questionId !== prevProps.questionId) {
            void this.fetchAnswerHistory(this.props.questionId);
        }
    }
    overlayClicked(event) {
        if (event.target instanceof HTMLDivElement && event.target.className.includes('js-undo-overlay')) {
            this.close();
        }
    }
    async fetchAnswerHistory(questionId) {
        try {
            let answers;
            if (this.props.examServerApi.getAnswerHistory) {
                answers = await this.props.examServerApi.getAnswerHistory(questionId);
            }
            else {
                // TODO: remove when getAnswerHistory isn't optional
                const answerHistoryResult = await axios.get(`/rest/answer-history/${questionId}`, {
                    cancelToken: this.source.token
                });
                const answerHistory = answerHistoryResult.data;
                answers = answerHistory.map(toAnswerHistoryEntry);
            }
            this.setState({ answers, selectedAnswerIndex: 0, loading: false, loadRetryTimeout: null });
        }
        catch (error) {
            console.error('Fetching answer history failed', error);
            if (!axios.isCancel(error)) {
                this.setState({
                    loadRetryTimeout: window.setTimeout(() => {
                        void this.fetchAnswerHistory(questionId);
                    }, 4000)
                });
            }
        }
    }
    close() {
        const timeout = this.state.loadRetryTimeout;
        if (timeout) {
            clearTimeout(timeout);
        }
        this.source.cancel();
        this.props.close();
    }
    render() {
        const selectedAnswer = this.state.answers[this.state.selectedAnswerIndex];
        const now = new Date().getTime();
        return (React.createElement(ModalDialog, { onClose: this.close.bind(this) },
            React.createElement("div", { onClick: this.overlayClicked.bind(this), className: "e-overlay js-undo-overlay", "aria-modal": "true" },
                React.createElement("div", { id: "undo", className: "e-undo-view" },
                    React.createElement(CloseButton, { close: this.close.bind(this) }),
                    this.state.loading ? (React.createElement(Loading, null)) : (React.createElement("div", { className: "e-undo-view-content" },
                        React.createElement("div", { className: "e-undo-view-answer-index js-undo-answer-index" }, this.state.answers.map((answer, index) => {
                            const timeSinceAnswer = now - new Date(answer.answerTime).getTime();
                            const toMinutes = Math.round(timeSinceAnswer / 1000 / 60);
                            return (React.createElement(UndoHistoryEntry, { key: new Date(answer.answerTime).getTime(), answerIndex: index, selected: index === this.state.selectedAnswerIndex, onChange: index => this.setState({ selectedAnswerIndex: index }), croppedAnswer: truncateAnswer(answer), minutesSinceAnswer: toMinutes, characterCount: countCharacters(answer), screenshotCount: countScreenshots(answer) }));
                        })),
                        React.createElement("div", { className: "e-undo-view-right-panel" },
                            React.createElement("div", { className: "e-undo-view-header js-undo-view-header" },
                                React.createElement("h3", { className: "e-undo-view-title js-undo-view-title" }, this.props.title)),
                            React.createElement(AnswerDisplay, { selectedAnswer: selectedAnswer }),
                            React.createElement(BottomBar, { selectedAnswer: selectedAnswer, selectedAnswerIndex: this.state.selectedAnswerIndex, restoreAnswer: this.props.restoreAnswer, questionId: this.props.questionId }))))))));
    }
}
const Loading = () => {
    const { t } = useExamTranslation();
    return React.createElement("div", { style: { padding: '10px' } }, t('undo.loading'));
};
const CloseButton = ({ close }) => {
    const { t } = useExamTranslation();
    return (React.createElement("div", { className: "e-undo-view-close-overlay-button", id: "closeUndoDialogButton", onClick: close, tabIndex: 0, role: "button", "aria-label": t('undo.close') },
        React.createElement("svg", { id: "Layer_1", "data-name": "Layer 1", xmlns: "http://www.w3.org/2000/svg", width: "30", height: "30", viewBox: "0 0 30 30" },
            React.createElement("defs", null,
                React.createElement("clipPath", { id: "clip-path" },
                    React.createElement("path", { d: "M141.57-89.324v-2.34H143.2v2.34A2.3,2.3,0,0,1,140.9-87.03H130.1a2.3,2.3,0,0,1-2.292-2.294v-17.029a2.294,2.294,0,0,1,2.292-2.292h10.8a2.3,2.3,0,0,1,2.295,2.292v2.342H141.57v-2.342a.669.669,0,0,0-.67-.667H130.1a.667.667,0,0,0-.667.667v17.029a.668.668,0,0,0,.667.669h10.8A.67.67,0,0,0,141.57-89.324Zm3.271-13.579a1.069,1.069,0,0,1,1.825-.755l5.065,5.065a1.065,1.065,0,0,1,0,1.511l-5.065,5.067a1.07,1.07,0,0,1-1.825-.757v-2.412h-6.633a2.3,2.3,0,0,1-2.3-2.3v-.7a2.3,2.3,0,0,1,2.3-2.3h6.633V-102.9", fill: "none", clipRule: "evenodd" })),
                React.createElement("clipPath", { id: "clip-path-2" },
                    React.createElement("ellipse", { cx: "10", cy: "-29.606", rx: "15", ry: "14.933", fill: "none" }))),
            React.createElement("title", null, "closeButton"),
            React.createElement("rect", { width: "30", height: "30", fill: "#fff", opacity: "0" }),
            React.createElement("line", { x1: "25", y1: "5", x2: "5", y2: "25", fill: "none", stroke: "#6d6d6d", strokeMiterlimit: "10", strokeWidth: "3" }),
            React.createElement("line", { x1: "5", y1: "5", x2: "25", y2: "25", fill: "none", stroke: "#6d6d6d", strokeMiterlimit: "10", strokeWidth: "3" }))));
};
const RestoreButtonLabel = () => {
    const { t } = useExamTranslation();
    return React.createElement("div", null, t('undo.restoreAnswer'));
};
//# sourceMappingURL=UndoView.js.map