import azure.cognitiveservices.speech as speechsdk
import random

class tts_manager:
    def __init__(self, azure_tts_api_key: str, region: str):
        """
        azure_tts_api_key: Your Azure Speech subscription key (from the Azure Portal)
        Found under: Azure Portal → Your Speech Resource → Keys and Endpoint → Key1 or Key2
        region: Azure service region.
        Example: "eastus", "westus2", "northeurope"
        Full list of supported regions:
        https://learn.microsoft.com/azure/ai-services/speech-service/regions
        """
        self.AZURE_VOICES = [
            "en-US-DavisNeural",
            "en-US-TonyNeural",
            "en-US-JasonNeural",
            "en-US-GuyNeural",
            "en-US-JaneNeural",
            "en-US-NancyNeural",
            "en-US-JennyNeural",
            "en-US-AriaNeural",
        ]

        self.AZURE_STYLES = [
            "angry",
            "cheerful",
            "excited",
            "hopeful",
            "sad",
            "shouting",
            "terrified",
            "unfriendly",
            "whispering"
        ]
        self.PREFIX_TO_STYLE = {
            "(angry)": "angry",
            "(cheerful)": "cheerful",
            "(excited)": "excited",
            "(hopeful)": "hopeful",
            "(sad)": "sad",
            "(shouting)": "shouting",
            "(terrified)": "terrified",
            "(unfriendly)": "unfriendly",
            "(whispering)": "whispering",
        }
        self.voice = "en-US-JaneNeural"
        self.style = "cheerful"

        self.speech_config = speechsdk.SpeechConfig(
            subscription = azure_tts_api_key,
            region = region
        )
        self.audio_config = speechsdk.audio.AudioOutputConfig(use_default_speaker=True)

        self.synthesizer = speechsdk.SpeechSynthesizer(
            speech_config=self.speech_config,
            audio_config=self.audio_config
        )

    def set_voice(self, voice: str):
        """Set default voice.
        Check self.AZURE_VOICES for available voices."""
        if voice == "random":
            self.voice = random.choice(self.AZURE_VOICES)
        elif voice in self.AZURE_VOICES: self.voice = voice
        else: print("voice not found, check self.AZURE_VOICES for available voices.")


    def set_style(self, style: str):
        """Set default style.
        Check self.AZURE_STYLES for available styles."""
        if style == "random":
            self.style = random.choice(self.AZURE_STYLES)
        elif style in self.AZURE_STYLES: self.style = style
        else: print("style not found, check self.AZURE_STYLES for available styles.")
    
    def speak(self, text: str, voice = None, style = None):
        """Translates text to speech and plays it on default speaker.
        if voice or style not specified, default is used."""
        if voice == None: voice = self.voice
        if style == None: style = self.style

        ssml = f"""<speak version="1.0"
xmlns="http://www.w3.org/2001/10/synthesis"
xmlns:mstts="http://www.w3.org/2001/mstts"
xml:lang="en-US">
<voice name="{voice}">
<mstts:express-as style="{style}">
{text}
</mstts:express-as>
</voice>
</speak>"""

        self.synthesizer.speak_ssml(ssml)

    async def speak_async(self, text: str, voice = None, style = None):
        if voice == None: voice = self.voice
        if style == None: style = self.style
        ssml = f"""<speak version="1.0"
xmlns="http://www.w3.org/2001/10/synthesis"
xmlns:mstts="http://www.w3.org/2001/mstts"
xml:lang="en-US">
<voice name="{voice}">
<mstts:express-as style="{style}">
{text}
</mstts:express-as>
</voice>
</speak>"""

        self.synthesizer.speak_ssml_async(ssml).get()

    async def speak_async_prefix(self, text: str):
        text = text.strip()
        if text.startswith(tuple(self.PREFIX_TO_STYLE.keys())):
            self.set_style(text[1:text.index(")")])
            text = text[text.index(")")+1:]
            print(text)

        ssml = f"""<speak version="1.0"
xmlns="http://www.w3.org/2001/10/synthesis"
xmlns:mstts="http://www.w3.org/2001/mstts"
xml:lang="en-US">
<voice name="{self.voice}">
<mstts:express-as style="{self.style}">
{text}
</mstts:express-as>
</voice>
</speak>"""
        
        self.synthesizer.speak_ssml_async(ssml).get()

    