# This file was auto-generated by Fern from our API Definition.

import typing
import urllib.parse
from contextlib import asynccontextmanager, contextmanager

import websockets.sync.client as websockets_sync_client
from ..core.api_error import ApiError
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.jsonable_encoder import jsonable_encoder
from ..core.query_encoder import encode_query
from ..core.remove_none_from_dict import remove_none_from_dict
from ..core.request_options import RequestOptions
from ..core.websocket_compat import InvalidWebSocketStatus, get_status_code
from .raw_client import AsyncRawSpeechToTextStreamingClient, RawSpeechToTextStreamingClient
from .socket_client import AsyncSpeechToTextStreamingSocketClient, SpeechToTextStreamingSocketClient
from .types.speech_to_text_streaming_flush_signal import SpeechToTextStreamingFlushSignal
from .types.speech_to_text_streaming_high_vad_sensitivity import SpeechToTextStreamingHighVadSensitivity
from .types.speech_to_text_streaming_input_audio_codec import SpeechToTextStreamingInputAudioCodec
from .types.speech_to_text_streaming_language_code import SpeechToTextStreamingLanguageCode
from .types.speech_to_text_streaming_mode import SpeechToTextStreamingMode
from .types.speech_to_text_streaming_model import SpeechToTextStreamingModel
from .types.speech_to_text_streaming_vad_signals import SpeechToTextStreamingVadSignals

try:
    from websockets.legacy.client import connect as websockets_client_connect  # type: ignore
except ImportError:
    from websockets import connect as websockets_client_connect  # type: ignore


class SpeechToTextStreamingClient:
    def __init__(self, *, client_wrapper: SyncClientWrapper):
        self._raw_client = RawSpeechToTextStreamingClient(client_wrapper=client_wrapper)

    @property
    def with_raw_response(self) -> RawSpeechToTextStreamingClient:
        """
        Retrieves a raw implementation of this client that returns raw responses.

        Returns
        -------
        RawSpeechToTextStreamingClient
        """
        return self._raw_client

    @contextmanager
    def connect(
        self,
        *,
        language_code: SpeechToTextStreamingLanguageCode,
        model: typing.Optional[SpeechToTextStreamingModel] = None,
        mode: typing.Optional[SpeechToTextStreamingMode] = None,
        sample_rate: typing.Optional[str] = None,
        high_vad_sensitivity: typing.Optional[SpeechToTextStreamingHighVadSensitivity] = None,
        positive_speech_threshold: typing.Optional[str] = None,
        negative_speech_threshold: typing.Optional[str] = None,
        min_speech_frames: typing.Optional[str] = None,
        first_turn_min_speech_frames: typing.Optional[str] = None,
        negative_frames_count: typing.Optional[str] = None,
        negative_frames_window: typing.Optional[str] = None,
        start_speech_volume_threshold: typing.Optional[str] = None,
        interrupt_min_speech_frames: typing.Optional[str] = None,
        pre_speech_pad_frames: typing.Optional[str] = None,
        num_initial_ignored_frames: typing.Optional[str] = None,
        vad_signals: typing.Optional[SpeechToTextStreamingVadSignals] = None,
        flush_signal: typing.Optional[SpeechToTextStreamingFlushSignal] = None,
        input_audio_codec: typing.Optional[SpeechToTextStreamingInputAudioCodec] = None,
        api_subscription_key: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.Iterator[SpeechToTextStreamingSocketClient]:
        """
        WebSocket channel for real-time speech to text streaming.

        **Note:** This API Reference page is provided for informational purposes only.
        The Try It playground may not provide the best experience for streaming audio.
        For optimal streaming performance, please use the SDK or implement your own WebSocket client.

        Parameters
        ----------
        language_code : SpeechToTextStreamingLanguageCode
            Specifies the language of the input audio in BCP-47 format.

            **Available Options (saarika:v2.5, legacy):**
            - `unknown` (default): Use when the language is not known; the API will auto-detect.
            - `hi-IN`: Hindi
            - `bn-IN`: Bengali
            - `gu-IN`: Gujarati
            - `kn-IN`: Kannada
            - `ml-IN`: Malayalam
            - `mr-IN`: Marathi
            - `od-IN`: Odia
            - `pa-IN`: Punjabi
            - `ta-IN`: Tamil
            - `te-IN`: Telugu
            - `en-IN`: English

            **Additional Options (saaras:v3, recommended):**
            - `as-IN`: Assamese
            - `ur-IN`: Urdu
            - `ne-IN`: Nepali
            - `kok-IN`: Konkani
            - `ks-IN`: Kashmiri
            - `sd-IN`: Sindhi
            - `sa-IN`: Sanskrit
            - `sat-IN`: Santali
            - `mni-IN`: Manipuri
            - `brx-IN`: Bodo
            - `mai-IN`: Maithili
            - `doi-IN`: Dogri

        model : typing.Optional[SpeechToTextStreamingModel]
            Specifies the model to use for speech-to-text conversion.

            - **saaras:v3** (default, recommended): State-of-the-art model with flexible output formats. Supports multiple modes via the `mode` parameter: transcribe, translate, verbatim, translit, codemix.

            - **saarika:v2.5** (legacy): Transcribes audio in the spoken language. Kept for backward compatibility.

        mode : typing.Optional[SpeechToTextStreamingMode]
            Mode of operation. **Only applicable when using saaras:v3 model.**

            Example audio: 'मेरा फोन नंबर है 9840950950'

            - **transcribe** (default): Standard transcription in the original language with proper formatting and number normalization.
              - Output: `मेरा फोन नंबर है 9840950950`

            - **translate**: Translates speech from any supported Indic language to English.
              - Output: `My phone number is 9840950950`

            - **verbatim**: Exact word-for-word transcription without normalization, preserving filler words and spoken numbers as-is.
              - Output: `मेरा फोन नंबर है नौ आठ चार zero नौ पांच zero नौ पांच zero`

            - **translit**: Romanization - Transliterates speech to Latin/Roman script only.
              - Output: `mera phone number hai 9840950950`

            - **codemix**: Code-mixed text with English words in English and Indic words in native script.
              - Output: `मेरा phone number है 9840950950`

        sample_rate : typing.Optional[str]
            Audio sample rate for the WebSocket connection. When specified as a connection parameter, only 16kHz and 8kHz are supported. 8kHz is only available via this connection parameter. If not specified, defaults to 16kHz.

        high_vad_sensitivity : typing.Optional[SpeechToTextStreamingHighVadSensitivity]
            Enable high VAD (Voice Activity Detection) sensitivity

        positive_speech_threshold : typing.Optional[str]
            VAD probability threshold (0.0–1.0) above which a frame is considered speech.
            Overrides the server default when provided.

        negative_speech_threshold : typing.Optional[str]
            VAD probability threshold (0.0–1.0) below which a frame is considered silence.
            Overrides the server default (or the high_vad_sensitivity preset) when provided.

        min_speech_frames : typing.Optional[str]
            Minimum number of consecutive speech frames required to start a speech segment.
            Overrides the server default when provided.

        first_turn_min_speech_frames : typing.Optional[str]
            Minimum speech frames required specifically for the first user turn.
            Overrides the server default when provided.

        negative_frames_count : typing.Optional[str]
            Number of negative (silence) frames needed within the window to end a speech segment.
            Overrides the server default (or the high_vad_sensitivity preset) when provided.

        negative_frames_window : typing.Optional[str]
            Sliding window size (in frames) over which negative frames are counted.
            Overrides the server default (or the high_vad_sensitivity preset) when provided.

        start_speech_volume_threshold : typing.Optional[str]
            Volume level (dB) below which audio is considered too quiet to be speech.
            When not provided, no volume-based filtering is applied.

        interrupt_min_speech_frames : typing.Optional[str]
            Minimum speech frames required to register a barge-in / interruption.
            Overrides the server default when provided.

        pre_speech_pad_frames : typing.Optional[str]
            Number of audio frames to prepend before the detected speech onset,
            ensuring the beginning of speech is not clipped.
            Overrides the server default when provided.

        num_initial_ignored_frames : typing.Optional[str]
            Number of leading audio frames to skip entirely at connection start.
            Useful for discarding connection setup noise.
            Overrides the server default when provided.

        vad_signals : typing.Optional[SpeechToTextStreamingVadSignals]
            Enable VAD signals in response

        flush_signal : typing.Optional[SpeechToTextStreamingFlushSignal]
            Signal to flush the audio buffer and finalize transcription

        input_audio_codec : typing.Optional[SpeechToTextStreamingInputAudioCodec]
            Audio codec/format of the input stream. Use this when sending raw PCM audio.
            Supported values: wav, pcm_s16le, pcm_l16, pcm_raw.

        api_subscription_key : typing.Optional[str]
            API subscription key for authentication

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        SpeechToTextStreamingSocketClient
        """
        ws_url = self._raw_client._client_wrapper.get_environment().production + "/speech-to-text/ws"
        _encoded_query_params = encode_query(
            jsonable_encoder(
                remove_none_from_dict(
                    {
                        "language-code": language_code,
                        "model": model,
                        "mode": mode,
                        "sample_rate": sample_rate,
                        "high_vad_sensitivity": high_vad_sensitivity,
                        "positive_speech_threshold": positive_speech_threshold,
                        "negative_speech_threshold": negative_speech_threshold,
                        "min_speech_frames": min_speech_frames,
                        "first_turn_min_speech_frames": first_turn_min_speech_frames,
                        "negative_frames_count": negative_frames_count,
                        "negative_frames_window": negative_frames_window,
                        "start_speech_volume_threshold": start_speech_volume_threshold,
                        "interrupt_min_speech_frames": interrupt_min_speech_frames,
                        "pre_speech_pad_frames": pre_speech_pad_frames,
                        "num_initial_ignored_frames": num_initial_ignored_frames,
                        "vad_signals": vad_signals,
                        "flush_signal": flush_signal,
                        "input_audio_codec": input_audio_codec,
                        **(
                            request_options.get("additional_query_parameters", {}) or {}
                            if request_options is not None
                            else {}
                        ),
                    }
                )
            )
        )
        if _encoded_query_params:
            ws_url = ws_url + "?" + urllib.parse.urlencode(_encoded_query_params)
        headers = self._raw_client._client_wrapper.get_headers()
        if api_subscription_key is not None:
            headers["Api-Subscription-Key"] = str(api_subscription_key)
        if request_options and "additional_headers" in request_options:
            headers.update(request_options["additional_headers"])
        try:
            with websockets_sync_client.connect(ws_url, additional_headers=headers) as protocol:
                yield SpeechToTextStreamingSocketClient(websocket=protocol)
        except InvalidWebSocketStatus as exc:
            status_code: int = get_status_code(exc)
            if status_code == 401:
                raise ApiError(
                    status_code=status_code,
                    headers=dict(headers),
                    body="Websocket initialized with invalid credentials.",
                )
            raise ApiError(
                status_code=status_code,
                headers=dict(headers),
                body="Unexpected error when initializing websocket connection.",
            )


class AsyncSpeechToTextStreamingClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._raw_client = AsyncRawSpeechToTextStreamingClient(client_wrapper=client_wrapper)

    @property
    def with_raw_response(self) -> AsyncRawSpeechToTextStreamingClient:
        """
        Retrieves a raw implementation of this client that returns raw responses.

        Returns
        -------
        AsyncRawSpeechToTextStreamingClient
        """
        return self._raw_client

    @asynccontextmanager
    async def connect(
        self,
        *,
        language_code: SpeechToTextStreamingLanguageCode,
        model: typing.Optional[SpeechToTextStreamingModel] = None,
        mode: typing.Optional[SpeechToTextStreamingMode] = None,
        sample_rate: typing.Optional[str] = None,
        high_vad_sensitivity: typing.Optional[SpeechToTextStreamingHighVadSensitivity] = None,
        positive_speech_threshold: typing.Optional[str] = None,
        negative_speech_threshold: typing.Optional[str] = None,
        min_speech_frames: typing.Optional[str] = None,
        first_turn_min_speech_frames: typing.Optional[str] = None,
        negative_frames_count: typing.Optional[str] = None,
        negative_frames_window: typing.Optional[str] = None,
        start_speech_volume_threshold: typing.Optional[str] = None,
        interrupt_min_speech_frames: typing.Optional[str] = None,
        pre_speech_pad_frames: typing.Optional[str] = None,
        num_initial_ignored_frames: typing.Optional[str] = None,
        vad_signals: typing.Optional[SpeechToTextStreamingVadSignals] = None,
        flush_signal: typing.Optional[SpeechToTextStreamingFlushSignal] = None,
        input_audio_codec: typing.Optional[SpeechToTextStreamingInputAudioCodec] = None,
        api_subscription_key: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.AsyncIterator[AsyncSpeechToTextStreamingSocketClient]:
        """
        WebSocket channel for real-time speech to text streaming.

        **Note:** This API Reference page is provided for informational purposes only.
        The Try It playground may not provide the best experience for streaming audio.
        For optimal streaming performance, please use the SDK or implement your own WebSocket client.

        Parameters
        ----------
        language_code : SpeechToTextStreamingLanguageCode
            Specifies the language of the input audio in BCP-47 format.

            **Available Options (saarika:v2.5, legacy):**
            - `unknown` (default): Use when the language is not known; the API will auto-detect.
            - `hi-IN`: Hindi
            - `bn-IN`: Bengali
            - `gu-IN`: Gujarati
            - `kn-IN`: Kannada
            - `ml-IN`: Malayalam
            - `mr-IN`: Marathi
            - `od-IN`: Odia
            - `pa-IN`: Punjabi
            - `ta-IN`: Tamil
            - `te-IN`: Telugu
            - `en-IN`: English

            **Additional Options (saaras:v3, recommended):**
            - `as-IN`: Assamese
            - `ur-IN`: Urdu
            - `ne-IN`: Nepali
            - `kok-IN`: Konkani
            - `ks-IN`: Kashmiri
            - `sd-IN`: Sindhi
            - `sa-IN`: Sanskrit
            - `sat-IN`: Santali
            - `mni-IN`: Manipuri
            - `brx-IN`: Bodo
            - `mai-IN`: Maithili
            - `doi-IN`: Dogri

        model : typing.Optional[SpeechToTextStreamingModel]
            Specifies the model to use for speech-to-text conversion.

            - **saaras:v3** (default, recommended): State-of-the-art model with flexible output formats. Supports multiple modes via the `mode` parameter: transcribe, translate, verbatim, translit, codemix.

            - **saarika:v2.5** (legacy): Transcribes audio in the spoken language. Kept for backward compatibility.

        mode : typing.Optional[SpeechToTextStreamingMode]
            Mode of operation. **Only applicable when using saaras:v3 model.**

            Example audio: 'मेरा फोन नंबर है 9840950950'

            - **transcribe** (default): Standard transcription in the original language with proper formatting and number normalization.
              - Output: `मेरा फोन नंबर है 9840950950`

            - **translate**: Translates speech from any supported Indic language to English.
              - Output: `My phone number is 9840950950`

            - **verbatim**: Exact word-for-word transcription without normalization, preserving filler words and spoken numbers as-is.
              - Output: `मेरा फोन नंबर है नौ आठ चार zero नौ पांच zero नौ पांच zero`

            - **translit**: Romanization - Transliterates speech to Latin/Roman script only.
              - Output: `mera phone number hai 9840950950`

            - **codemix**: Code-mixed text with English words in English and Indic words in native script.
              - Output: `मेरा phone number है 9840950950`

        sample_rate : typing.Optional[str]
            Audio sample rate for the WebSocket connection. When specified as a connection parameter, only 16kHz and 8kHz are supported. 8kHz is only available via this connection parameter. If not specified, defaults to 16kHz.

        high_vad_sensitivity : typing.Optional[SpeechToTextStreamingHighVadSensitivity]
            Enable high VAD (Voice Activity Detection) sensitivity

        positive_speech_threshold : typing.Optional[str]
            VAD probability threshold (0.0–1.0) above which a frame is considered speech.
            Overrides the server default when provided.

        negative_speech_threshold : typing.Optional[str]
            VAD probability threshold (0.0–1.0) below which a frame is considered silence.
            Overrides the server default (or the high_vad_sensitivity preset) when provided.

        min_speech_frames : typing.Optional[str]
            Minimum number of consecutive speech frames required to start a speech segment.
            Overrides the server default when provided.

        first_turn_min_speech_frames : typing.Optional[str]
            Minimum speech frames required specifically for the first user turn.
            Overrides the server default when provided.

        negative_frames_count : typing.Optional[str]
            Number of negative (silence) frames needed within the window to end a speech segment.
            Overrides the server default (or the high_vad_sensitivity preset) when provided.

        negative_frames_window : typing.Optional[str]
            Sliding window size (in frames) over which negative frames are counted.
            Overrides the server default (or the high_vad_sensitivity preset) when provided.

        start_speech_volume_threshold : typing.Optional[str]
            Volume level (dB) below which audio is considered too quiet to be speech.
            When not provided, no volume-based filtering is applied.

        interrupt_min_speech_frames : typing.Optional[str]
            Minimum speech frames required to register a barge-in / interruption.
            Overrides the server default when provided.

        pre_speech_pad_frames : typing.Optional[str]
            Number of audio frames to prepend before the detected speech onset,
            ensuring the beginning of speech is not clipped.
            Overrides the server default when provided.

        num_initial_ignored_frames : typing.Optional[str]
            Number of leading audio frames to skip entirely at connection start.
            Useful for discarding connection setup noise.
            Overrides the server default when provided.

        vad_signals : typing.Optional[SpeechToTextStreamingVadSignals]
            Enable VAD signals in response

        flush_signal : typing.Optional[SpeechToTextStreamingFlushSignal]
            Signal to flush the audio buffer and finalize transcription

        input_audio_codec : typing.Optional[SpeechToTextStreamingInputAudioCodec]
            Audio codec/format of the input stream. Use this when sending raw PCM audio.
            Supported values: wav, pcm_s16le, pcm_l16, pcm_raw.

        api_subscription_key : typing.Optional[str]
            API subscription key for authentication

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncSpeechToTextStreamingSocketClient
        """
        ws_url = self._raw_client._client_wrapper.get_environment().production + "/speech-to-text/ws"
        _encoded_query_params = encode_query(
            jsonable_encoder(
                remove_none_from_dict(
                    {
                        "language-code": language_code,
                        "model": model,
                        "mode": mode,
                        "sample_rate": sample_rate,
                        "high_vad_sensitivity": high_vad_sensitivity,
                        "positive_speech_threshold": positive_speech_threshold,
                        "negative_speech_threshold": negative_speech_threshold,
                        "min_speech_frames": min_speech_frames,
                        "first_turn_min_speech_frames": first_turn_min_speech_frames,
                        "negative_frames_count": negative_frames_count,
                        "negative_frames_window": negative_frames_window,
                        "start_speech_volume_threshold": start_speech_volume_threshold,
                        "interrupt_min_speech_frames": interrupt_min_speech_frames,
                        "pre_speech_pad_frames": pre_speech_pad_frames,
                        "num_initial_ignored_frames": num_initial_ignored_frames,
                        "vad_signals": vad_signals,
                        "flush_signal": flush_signal,
                        "input_audio_codec": input_audio_codec,
                        **(
                            request_options.get("additional_query_parameters", {}) or {}
                            if request_options is not None
                            else {}
                        ),
                    }
                )
            )
        )
        if _encoded_query_params:
            ws_url = ws_url + "?" + urllib.parse.urlencode(_encoded_query_params)
        headers = self._raw_client._client_wrapper.get_headers()
        if api_subscription_key is not None:
            headers["Api-Subscription-Key"] = str(api_subscription_key)
        if request_options and "additional_headers" in request_options:
            headers.update(request_options["additional_headers"])
        try:
            async with websockets_client_connect(ws_url, extra_headers=headers) as protocol:
                yield AsyncSpeechToTextStreamingSocketClient(websocket=protocol)
        except InvalidWebSocketStatus as exc:
            status_code: int = get_status_code(exc)
            if status_code == 401:
                raise ApiError(
                    status_code=status_code,
                    headers=dict(headers),
                    body="Websocket initialized with invalid credentials.",
                )
            raise ApiError(
                status_code=status_code,
                headers=dict(headers),
                body="Unexpected error when initializing websocket connection.",
            )
