import os

missing = []
for lib in ["pyttsx3"]:
    try:
        __import__(lib)
    except ImportError:
        missing.append(lib)

if missing:
    print(f"Error: Missing libraries:\n{', '.join(missing)}")
    print("  install: pip install pydub simpleaudio pyttsx3")
    input("\nPress ENTER to terminate>>\n")
    sys.exit(1)

from tktts_base import apply_replacements, normalize_speaker, split_dialogue
import pyttsx3


TTS_ENGINE_NAME = 'pyttsx3'
DEFAULT_PYTTSX3_VOICE = 'Haruka'


def get_available_voices_info():
    try:
        engine = pyttsx3.init()
    except Exception as e:
        print(f"Error in tktts_pyttsx3.get_available_voices(): {TTS_ENGINE_NAME}の初期化エラー: {e}")
        return False
    
    voices = []
    for v in engine.getProperty("voices"):
        voices.append({"name": v.name, "id": v.id, "lang": v.languages})
#        print(f"  Name: {v.name}, Lang: {v.languages}, ID: {v.id}")
    engine.stop()

    return voices

def get_available_voices():
    voices = get_available_voices_info()
    if not voices: return False
    
    voice_names = []
    for v in voices:
        voice_names.append(v['name'])

    return voice_names


def list_available_voices():
    print(f"=== 利用可能な {TTS_ENGINE_NAME} voices ===")
    voices = get_available_voices_info()
    if not voices: return False
    
    for v in voices:
        print(f"  Name: {v['name']}, Lang: {v['lang']}, ID: {v['id']}")

    return True

# Windowsでは、speak()は１回しか呼び出せない
def speak(outfile, text, voice, speak_rate = None):
    is_save_mode = bool(outfile)

    engine = pyttsx3.init()
    voices = engine.getProperty("voices")
    engine.setProperty("rate", speak_rate)

    for v in voices:
        if target_voice.lower() in v.name.lower():
            engine.setProperty("voice", v.id)
            break

    if is_save_mode:
        engine.save_to_file(text, outfile)
    else:
        engine.say(text)

    engine.runAndWait()
    engine.stop()

    if is_save_mode:
        if len(outfile) > 0 and os.path.exists(outfile):
            print(f"　Error: ファイル [{outfile}] の出力に失敗しました")
            return None
        return outfile

    return True

def speak_dialogue(dialogue, replacements, target_voices, speakers = {}, speak_rate = 150, 
            temp_dir = None, outfile = None, ext = "wav", cfg = None):
    is_save_mode = bool(outfile)

    print()
    print("tktts_pyttsx3.speak_dialogue(): ")
    print(f"　出力ファイル: {outfile}")
    print(f"  is_save_mode: {is_save_mode}")
    print("target_voices:", target_voices)

    engine = pyttsx3.init()
    voices = engine.getProperty("voices")
    engine.setProperty("rate", speak_rate)

    tmpfiles = []
    text_all = ""
    idx = 1
    for i, _dialogue in enumerate(dialogue):
        print()
        print(f"Dialogue {i:04d}:")
#        print(f"i={i}: {speaker}")
        dialogue_list = split_dialogue(_dialogue, target_voices, speakers = speakers, 
                            default_voice = DEFAULT_PYTTSX3_VOICE, is_monologue = cfg.monologue)
        for speaker, text in dialogue_list:
            tmpfile = os.path.join(temp_dir, f"tmp_{idx:03d}.{ext}")
            text = apply_replacements(text, replacements)
            if type(target_voices) is str: speaker = target_voices

            speaker = normalize_speaker(speaker)
            if type(target_voices) is str: 
                target_voice = speaker
            else:
                target_voice = target_voices[speaker]
            print(f"  {idx:04d}: voice={speaker} (id={target_voice}): ", end = "")
            print(text)

            for v in voices:
                if target_voice.lower() in v.name.lower():
                    engine.setProperty("voice", v.id)
                    break

            print(f"{i:04d}: {speaker}: {target_voice}: {text}")
            if is_save_mode:
#                tmpfile = os.path.join(temp_dir, f"tmp_{i:03d}.wav")
                tmpfiles.append(tmpfile)
                engine.save_to_file(text, tmpfile)
            else:
                text_all += "\n" + text
            idx += 1

    # まとめて音声生成（ハングしない＆rate反映）
    if is_save_mode:
        print(f"\n{TTS_ENGINE_NAME}で音声ファイルを一時ファイルに生成中...")
    else:
        print(f"\n{TTS_ENGINE_NAME}で音声ファイルを再生中...")
        engine.say(text_all)

    engine.runAndWait()
    engine.stop()
    if is_save_mode and len(tmpfile) > 0 and os.path.exists(tmpfile[0]):
        print(f"　Error: ファイル [{tmpfile[0]} など] の出力に失敗しました")
        return False, tmpfiles

    if is_save_mode:
        return True, tmpfiles
    else:
        return True, {}
    