(function () {
    'use strict';

    var config = window.PodcastmakerAudioAnalytics || {};
    if (!config.ajaxUrl || !config.action || !config.postId) {
        return;
    }

    function randomId(prefix) {
        if (window.crypto && typeof window.crypto.randomUUID === 'function') {
            return prefix + window.crypto.randomUUID().replace(/-/g, '');
        }
        return prefix + Date.now() + Math.random().toString(16).slice(2);
    }

    function getCookie(name) {
        var match = document.cookie.match(new RegExp('(?:^|; )' + name + '=([^;]*)'));
        return match ? decodeURIComponent(match[1]) : '';
    }

    function setCookie(name, value, days) {
        var expires = new Date(Date.now() + (days * 86400000)).toUTCString();
        document.cookie = name + '=' + encodeURIComponent(value) + '; expires=' + expires + '; path=/; SameSite=Lax';
    }

    function getVisitorId() {
        var key = 'quikvox_visitor_id';
        var value = getCookie(key);
        if (!value) {
            value = randomId('qv_');
            setCookie(key, value, 365);
        }
        return value;
    }

    function getAudioSrc(audio) {
        return audio.currentSrc || audio.getAttribute('src') || '';
    }

    function isTrackableAudio(audio) {
        var src = getAudioSrc(audio);
        if (!src) {
            return false;
        }
        if (audio.dataset.quikvoxAudio === '1') {
            return true;
        }
        return src.indexOf(config.generatedPrefix || 'podcast_audio_') !== -1;
    }

    function getProgressPercent(audio) {
        if (!audio.duration || !isFinite(audio.duration) || audio.duration <= 0) {
            return 0;
        }
        return Math.max(0, Math.min(100, (audio.currentTime / audio.duration) * 100));
    }

    function getProgressBucket(percent) {
        if (percent >= 90) {
            return 90;
        }
        if (percent >= 60) {
            return 60;
        }
        if (percent >= 30) {
            return 30;
        }
        return 0;
    }

    function sendEvent(payload, useKeepalive) {
        var formData = new FormData();
        Object.keys(payload).forEach(function (key) {
            formData.append(key, payload[key]);
        });

        fetch(config.ajaxUrl, {
            method: 'POST',
            body: formData,
            credentials: 'same-origin',
            keepalive: !!useKeepalive
        }).catch(function () {
            return null;
        });
    }

    function bindAudio(audio, index) {
        if (!isTrackableAudio(audio) || audio.dataset.quikvoxTracked === '1') {
            return;
        }

        audio.dataset.quikvoxTracked = '1';

        var visitorId = getVisitorId();
        var state = {
            playbackSessionId: '',
            started: false,
            completed: false,
            lastCheckpointBucket: 0,
            lastCheckpointPercent: 0,
            thresholds: {
                30: false,
                60: false,
                90: false
            }
        };

        function createPayload(eventType, progressPercent, progressBucket) {
            return {
                action: config.action,
                nonce: config.nonce || '',
                post_id: String(config.postId),
                visitor_id: visitorId,
                playback_session_id: state.playbackSessionId,
                audio_url: getAudioSrc(audio),
                audio_index: String(index),
                event_type: eventType,
                progress_percent: String(progressPercent.toFixed(2)),
                progress_bucket: String(progressBucket),
                duration_seconds: String(audio.duration && isFinite(audio.duration) ? audio.duration.toFixed(2) : '0')
            };
        }

        function beginSession() {
            state.playbackSessionId = randomId('play_');
            state.started = true;
            state.completed = false;
            state.lastCheckpointBucket = 0;
            state.lastCheckpointPercent = 0;
            state.thresholds[30] = false;
            state.thresholds[60] = false;
            state.thresholds[90] = false;
            sendEvent(createPayload('start', 0, 0), false);
        }

        function ensureSession() {
            if (!state.started || state.completed) {
                beginSession();
            }
        }

        function maybeSendThresholds() {
            var percent = getProgressPercent(audio);
            [30, 60, 90].forEach(function (threshold) {
                if (percent >= threshold && !state.thresholds[threshold]) {
                    state.thresholds[threshold] = true;
                    sendEvent(createPayload('progress', percent, threshold), false);
                }
            });
        }

        function sendCheckpoint(force) {
            if (!state.started) {
                return;
            }

            var percent = getProgressPercent(audio);
            var bucket = getProgressBucket(percent);
            if (!force && bucket === state.lastCheckpointBucket && Math.abs(percent - state.lastCheckpointPercent) < 5) {
                return;
            }

            state.lastCheckpointBucket = bucket;
            state.lastCheckpointPercent = percent;
            sendEvent(createPayload('checkpoint', percent, bucket), force);
        }

        audio.addEventListener('play', function () {
            ensureSession();
        });

        audio.addEventListener('timeupdate', function () {
            ensureSession();
            maybeSendThresholds();
        });

        audio.addEventListener('pause', function () {
            sendCheckpoint(false);
        });

        audio.addEventListener('ended', function () {
            ensureSession();
            maybeSendThresholds();
            sendEvent(createPayload('complete', 100, 100), true);
            state.completed = true;
            state.started = false;
        });

        audio.addEventListener('seeked', function () {
            if (state.started && !state.completed) {
                maybeSendThresholds();
            }
        });

        document.addEventListener('visibilitychange', function () {
            if (document.visibilityState === 'hidden') {
                sendCheckpoint(true);
            }
        });

        window.addEventListener('pagehide', function () {
            sendCheckpoint(true);
        });
    }

    function init() {
        var audios = document.querySelectorAll('audio');
        audios.forEach(function (audio, index) {
            bindAudio(audio, index + 1);
        });
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }
})();
