import Dexie from 'dexie';
/** Creates a mock Exam Server API, backed by a local IndexedDB database. */
export function indexedDBExamServerAPI(examUuid, resolveAttachment) {
    const db = new (class extends Dexie {
        constructor() {
            super('exam');
            this.version(1).stores({
                answer: '[examUuid+questionId], examUuid',
                audio: 'audioId'
            });
        }
    })();
    // Emulate real exam restricted audio playback by playing the audio files in a
    // HTML5 <audio> tag. The tag is made visible when starting playback and hidden
    // when playback finishes.
    const audioPlayer = new Audio();
    audioPlayer.classList.add('audio-player');
    audioPlayer.controls = true;
    audioPlayer.onended = () => {
        audioPlayer.classList.add('audio-player--animating');
        audioPlayer.classList.remove('audio-player--visible');
    };
    const animationFinished = () => audioPlayer.classList.remove('audio-player--animating');
    audioPlayer.addEventListener('transitionend', animationFinished);
    audioPlayer.addEventListener('transitioncancel', animationFinished);
    document.body.appendChild(audioPlayer);
    const examServerApi = {
        setCasStatus: casStatus => Promise.resolve(casStatus),
        getAnswers: () => db.answer.where({ examUuid }).toArray(),
        saveAnswer: async (answer) => {
            await db.answer.put({ ...answer, examUuid });
        },
        async saveAudio(questionId, audio) {
            const audioId = `${examUuid}-${questionId}`;
            const previouslySavedAudio = await db.audio.get(audioId);
            const combinedAudio = previouslySavedAudio
                ? new Blob([previouslySavedAudio.blob, audio], { type: audio.type })
                : audio;
            return new Promise((resolve, reject) => {
                const reader = new FileReader();
                reader.onload = async () => {
                    const dataUrl = String(reader.result);
                    await db.audio.put({ blob: combinedAudio, dataUrl, audioId });
                    resolve(dataUrl);
                };
                reader.onerror = () => {
                    reader.abort();
                    reject(reader.error);
                };
                reader.readAsDataURL(combinedAudio);
            });
        },
        async deleteAudio(dataUrl) {
            const audio = await db.audio
                .filter(audio => audio.dataUrl.includes(dataUrl) // operator == does not find audio, because of value.split('/') in AudioAnswer.tsx
            )
                .first();
            if (audio) {
                await db.audio.delete(audio.audioId);
            }
            return Promise.resolve();
        },
        async playAudio(src) {
            audioPlayer.src = resolveAttachment(src);
            try {
                await audioPlayer.play();
                audioPlayer.classList.add('audio-player--visible', 'audio-player--animating');
                return 'ok';
            }
            catch (err) {
                console.error('Playing audio failed', err);
                return 'other-error';
            }
        },
        async playRestrictedAudio(src) {
            return examServerApi.playAudio(src);
        },
        getRestrictedAudio() {
            throw new Error('other-error');
        },
        saveScreenshot(_, file) {
            return new Promise((resolve, reject) => {
                const reader = new FileReader();
                reader.onload = () => {
                    resolve(String(reader.result));
                };
                reader.onerror = () => {
                    reader.abort();
                    reject(reader.error);
                };
                reader.readAsDataURL(file);
            });
        }
    };
    return examServerApi;
}
//# sourceMappingURL=indexedDBExamServerAPI.js.map