import { h } from "@stencil/core";
import WaveSurfer from "wavesurfer.js";
import RecordPlugin from "wavesurfer.js/dist/plugins/record.js";
import { getSpeechToText } from "../../../../utils/utils";
import { MediaRecorder as ExtendableMediaRecorder, register } from "extendable-media-recorder";
import { connect } from "extendable-media-recorder-wav-encoder";
import { getParentComponentState, setActiveParentComponent } from "../../../../utils/state/app-store";
import { getCountryByTimeZone, validateChinaTime } from "../../../../utils/parseHelper/parseHelper";
export class AudioRecorder {
    constructor() {
        this.isRecording = false;
        this.isProcessing = false;
        this.time = 0;
        this.transcript = ""; // To store the recognized text
        this.fullTranscript = ""; // To store the full transcript
        this.isSpeechRecognitionSupported = true;
        this.userCountry = "";
        this.audioBase64 = "";
        this.originalMediaRecorder = window.MediaRecorder;
        this.pendingStop = false;
        this.recognitionEnded = false;
    }
    resolveParentState() {
        const scopedState = getParentComponentState(this.componentType);
        return {
            dataKey: this.dataKey || scopedState.dataKey,
            dataMode: this.dataMode || scopedState.dataMode,
        };
    }
    async componentWillLoad() {
        var _a;
        this.isSpeechRecognitionSupported = this.checkSpeechRecognitionSupport();
        const userTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
        this.userCountry = getCountryByTimeZone(userTimeZone);
        if (validateChinaTime(userTimeZone)) {
            console.warn("User is likely in China, which may have limited Web Speech API support. Falling back to audio processing mode.");
            this.isSpeechRecognitionSupported = false;
        }
        // 1. Check if the 'audio/wav' encoder is already registered
        if (!window.MediaRecorder.isTypeSupported("audio/wav")) {
            try {
                await register(await connect());
                // console.log('WAV encoder registered successfully.')
            }
            catch (err) {
                // Check if the error is just a "duplicate" warning
                if ((_a = err.message) === null || _a === void 0 ? void 0 : _a.includes("already an encoder")) {
                    console.warn("WAV encoder was already registered. Continuing...");
                }
                else {
                    console.error("Unexpected encoder registration error:", err);
                }
                // console.warn('Encoder registration failed or was already handled:', err)
            }
        }
    }
    checkSpeechRecognitionSupport() {
        if (typeof window === "undefined") {
            return false;
        }
        return "SpeechRecognition" in window || "webkitSpeechRecognition" in window;
    }
    getRecognitionLanguage() {
        var _a, _b;
        if (typeof navigator === "undefined")
            return "en-US";
        const primaryLanguage = (_b = (_a = navigator.languages) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : navigator.language;
        return primaryLanguage || "en-US";
    }
    async startRecording() {
        // if (!this.isSpeechRecognitionSupported) {
        //   return
        // }
        this.fullTranscript = "";
        this.pendingStop = false;
        this.recognitionEnded = false;
        this.startRecord.emit(this);
        this.isRecording = true;
        setActiveParentComponent(this.componentType);
        try {
            // 1. CRITICAL: Override the global MediaRecorder so WaveSurfer uses it
            // Please ignore this line, because it is necessary for WaveSurfer to use the ExtendableMediaRecorder
            window.MediaRecorder = ExtendableMediaRecorder;
            this.startRecognition();
            setTimeout(() => this.createWaveSurfer(), 500);
            this.time = 0;
            this.timer = setInterval(() => {
                this.time++;
            }, 500);
        }
        catch (error) {
            console.error("Error accessing microphone:", error);
        }
    }
    createWaveSurfer() {
        // Destroy the previous wavesurfer instance
        if (this.wavesurfer) {
            this.wavesurfer.destroy();
        }
        const styles = getComputedStyle(this.element);
        const readCssVar = (name) => styles.getPropertyValue(name).trim();
        const waveColor = readCssVar("--ai12z-audio-wave-color") ||
            readCssVar("--ai12zBot-v2-searchbar-mic-color") ||
            readCssVar("--ai12z-mic-color") ||
            readCssVar("--ai12z-primary-color") ||
            "#007bff";
        const progressColor = readCssVar("--ai12z-audio-progress-color") || readCssVar("--ai12zBot-v2-secondary-accent") || readCssVar("--ai12z-secondary-accent") || waveColor;
        // 2. Temporarily swap to the Extendable version
        window.MediaRecorder = ExtendableMediaRecorder;
        // console.log("Creating new Wavesurfer instance", this.element.querySelector("#mic"))
        try {
            // Create a new Wavesurfer instance
            this.wavesurfer = WaveSurfer.create({
                container: this.element.querySelector("#mic"),
                waveColor,
                progressColor,
                barWidth: 3, // Small bar width
                barGap: 2, // Slight gap between bars
                height: 30,
                // plugins: [
                //   RecordPlugin.create({
                //     scrollingWaveform: true,
                //   }),
                // ],
            });
            // Initialize the Record plugin
            this.record = this.wavesurfer.registerPlugin(RecordPlugin.create({
                renderRecordedAudio: false,
                scrollingWaveform: true,
                continuousWaveform: true,
                continuousWaveformDuration: 30, // optional
                mimeType: "audio/wav",
            }));
            // Render recorded audio
            this.record.on("record-end", (blob) => {
                // DEBUG: auto-download to verify the file plays correctly
                // const url = URL.createObjectURL(blob)
                // const a = document.createElement('a')
                // a.href = url
                // a.download = `recording-${Date.now()}.wav`
                // a.click()
                // URL.revokeObjectURL(url)
                const reader = new FileReader();
                reader.onloadend = async () => {
                    this.audioBase64 = reader.result;
                    // IF we are in processing mode (meaning WebSpeech failed/wasn't supported)
                    if (this.isProcessing) {
                        try {
                            const parentState = this.resolveParentState();
                            const response = await getSpeechToText(parentState.dataKey, this.getRecognitionLanguage(), parentState.dataMode, this.audioBase64);
                            if (response.success) {
                                this.sendTranscript.emit(response.transcript);
                            }
                            else {
                                this.sendTranscript.emit(""); // Emit empty transcript on failure to trigger fallback handling
                            }
                            this.stopRecord.emit(this);
                        }
                        catch (error) {
                            console.error("API Error:", error);
                            this.stopRecord.emit(this);
                        }
                        finally {
                            this.isProcessing = false;
                            this.isRecording = false;
                            this.audioBase64 = "";
                            window.MediaRecorder = this.originalMediaRecorder;
                        }
                    }
                };
                reader.readAsDataURL(blob);
            });
            // this.record = this.wavesurfer.getActivePlugins()[0]
            this.record.startRecording();
        }
        catch (error) {
            console.error("Failed to initialize WaveSurfer or RecordPlugin:", error);
            this.isRecording = false; // Reset state if init fails
            window.MediaRecorder = this.originalMediaRecorder;
        }
    }
    startRecognition() {
        if (this.isSpeechRecognitionSupported) {
            const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
            this.recognition = new SpeechRecognition();
            this.recognition.lang = this.getRecognitionLanguage(); // Set recognition language from browser settings
            this.recognition.interimResults = true; // Only get final results
            // Start recording
            this.recognition.start();
            // Capture the result when speech is recognized
            this.recognition.onresult = (event) => {
                let transcript = "";
                for (let i = event.resultIndex; i < event.results.length; i++) {
                    transcript += event.results[i][0].transcript;
                }
                this.fullTranscript = transcript; // Store the full transcript
                // console.log("Recognized Speech: ", this.fullTranscript)
                this.transcript = this.fullTranscript;
                // this.sendTranscript.emit(transcript)
            };
            // Handle errors (e.g., no speech, microphone access issues)
            this.recognition.onerror = (event) => {
                console.error("Error occurred in recognition:", event.error);
            };
            // Stop recording automatically after speech ends
            this.recognition.onend = () => {
                this.recognitionEnded = true;
                if (this.pendingStop) {
                    this.pendingStop = false;
                    this.resolveStopAction();
                }
            };
        }
    }
    resolveStopAction() {
        if (this.fullTranscript || this.isSpeechRecognitionSupported) {
            this.sendTranscript.emit(this.fullTranscript);
            this.stopRecord.emit(this);
            this.isRecording = false;
            window.MediaRecorder = this.originalMediaRecorder;
        }
        else {
            this.isProcessing = true;
        }
    }
    stopRecording(source) {
        if (this.record.isRecording()) {
            this.record.stopRecording();
        }
        // Stop speech recognition
        if (this.recognition) {
            this.recognition.stop();
        }
        // this.isRecording = false
        clearInterval(this.timer);
        if (source === "stop") {
            if (this.isSpeechRecognitionSupported && this.recognition) {
                if (this.recognitionEnded) {
                    // onend already fired before stop was clicked — decide now
                    this.resolveStopAction();
                }
                else {
                    // onend hasn't fired yet — let it call resolveStopAction when it does
                    this.pendingStop = true;
                }
            }
            else {
                // No WebSpeech available — go straight to API fallback
                this.isProcessing = true;
            }
        }
    }
    render() {
        const minutes = Math.floor(this.time / 60);
        const seconds = this.time % 60;
        return (h("div", { key: 'b73747279b29f4a1caf317a5d0f00da382315346', class: "flex w-full" }, (this.isRecording || this.isProcessing) && (h("div", { key: '534a01d1be9ae431f46029615db42c87a2587f36', class: `relative flex items-center w-full rounded-full` }, this.isRecording && (h("button", { key: '862cdaa52da77d810a441853181c06f3a26da726', "aria-label": "Cancel Recording", onClick: e => {
                e.preventDefault();
                this.stopRecording("cancel");
            }, class: "w-10 h-10 rounded-full  flex items-center justify-center text-white" }, "\u274C")), h("div", { key: '62495256b25dc06fe0653702ae080e33c7745c8c', id: "mic", style: { width: "100%" } }), this.isRecording && !this.isProcessing ? (h("div", { class: "ml-auto text-blue-600 font-semibold" }, String(minutes).padStart(2, "0"), ":", String(seconds).padStart(2, "0"))) : null, (this.isRecording || this.isProcessing) && (h("button", { key: '036e203205dfc398ed7152f796fc43d7b1bad24a', "aria-label": "Confirm Recording", disabled: this.isProcessing, onClick: e => {
                e.preventDefault();
                if (!this.isProcessing)
                    this.stopRecording("stop");
            }, class: `w-10 h-10 ml-2 rounded-full flex items-center justify-center ${this.isProcessing ? "cursor-not-allowed" : "text-blue-600"}` }, this.isProcessing ? (h("svg", { class: "activity-spinner", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg" }, h("line", { x1: "12", y1: "2", x2: "12", y2: "5", "stroke-width": "2", "stroke-linecap": "round", style: { "--n": "0" } }), h("line", { x1: "16.24", y1: "3.76", x2: "14.12", y2: "5.88", "stroke-width": "2", "stroke-linecap": "round", style: { "--n": "1" } }), h("line", { x1: "19", y1: "7.76", x2: "16.24", y2: "9.24", "stroke-width": "2", "stroke-linecap": "round", style: { "--n": "2" } }), h("line", { x1: "20", y1: "12", x2: "17", y2: "12", "stroke-width": "2", "stroke-linecap": "round", style: { "--n": "3" } }), h("line", { x1: "19", y1: "16.24", x2: "16.24", y2: "14.76", "stroke-width": "2", "stroke-linecap": "round", style: { "--n": "4" } }), h("line", { x1: "16.24", y1: "20.24", x2: "14.12", y2: "18.12", "stroke-width": "2", "stroke-linecap": "round", style: { "--n": "5" } }), h("line", { x1: "12", y1: "22", x2: "12", y2: "19", "stroke-width": "2", "stroke-linecap": "round", style: { "--n": "6" } }), h("line", { x1: "7.76", y1: "20.24", x2: "9.88", y2: "18.12", "stroke-width": "2", "stroke-linecap": "round", style: { "--n": "7" } }), h("line", { x1: "5", y1: "16.24", x2: "7.76", y2: "14.76", "stroke-width": "2", "stroke-linecap": "round", style: { "--n": "8" } }), h("line", { x1: "4", y1: "12", x2: "7", y2: "12", "stroke-width": "2", "stroke-linecap": "round", style: { "--n": "9" } }), h("line", { x1: "5", y1: "7.76", x2: "7.76", y2: "9.24", "stroke-width": "2", "stroke-linecap": "round", style: { "--n": "10" } }), h("line", { x1: "7.76", y1: "3.76", x2: "9.88", y2: "5.88", "stroke-width": "2", "stroke-linecap": "round", style: { "--n": "11" } }))) : (h("span", { class: "text-blue-600 font-sans" }, "\u2714")))))), !this.isRecording && !this.isProcessing && (h("button", { key: 'ad24a6225403a8983100667054aa45f3ed5c24a8', "aria-label": "Start Recording", title: "Start Recording", onClick: e => {
                e.preventDefault();
                this.startRecording();
            }, class: `flex ${this.componentType === "search" || this.componentType === "cta" ? "p-1.5 mr-0.5 self-center mt-0.5" : "w-10 h-8 p-0 mt-4"}` }, h("svg", { key: '7e1b80a53b24d446cdf9bf77512d2bdea8a29450', xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", class: `w-5 h-5 translate-y-[0.5px] ${this.componentType === "search" || this.componentType === "cta" ? "mic-icon" : "mic-botIcon"}` }, h("path", { key: '73917f2f7ffc7f6c243394797ffe83944279bc27', d: "M7 4a3 3 0 016 0v6a3 3 0 11-6 0V4z" }), h("path", { key: 'bc2e12c016990bdbb1aaeee292e612e11d7993c8', d: "M5.5 9.643a.75.75 0 00-1.5 0V10c0 3.06 2.29 5.585 5.25 5.954V17.5h-1.5a.75.75 0 000 1.5h4.5a.75.75 0 000-1.5h-1.5v-1.546A6.001 6.001 0 0016 10v-.357a.75.75 0 00-1.5 0V10a4.5 4.5 0 01-9 0v-.357z" }))))));
    }
    static get is() { return "audio-recorder"; }
    static get originalStyleUrls() {
        return {
            "$": ["./audio-recorder.css"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["audio-recorder.css"]
        };
    }
    static get properties() {
        return {
            "componentType": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "component-type"
            }
        };
    }
    static get states() {
        return {
            "dataKey": {},
            "dataMode": {},
            "isRecording": {},
            "isProcessing": {},
            "time": {},
            "transcript": {},
            "fullTranscript": {},
            "isSpeechRecognitionSupported": {},
            "userCountry": {}
        };
    }
    static get events() {
        return [{
                "method": "startRecord",
                "name": "startRecord",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "complexType": {
                    "original": "any",
                    "resolved": "any",
                    "references": {}
                }
            }, {
                "method": "stopRecord",
                "name": "stopRecord",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "complexType": {
                    "original": "any",
                    "resolved": "any",
                    "references": {}
                }
            }, {
                "method": "sendTranscript",
                "name": "sendTranscript",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "complexType": {
                    "original": "any",
                    "resolved": "any",
                    "references": {}
                }
            }];
    }
    static get elementRef() { return "element"; }
}
