#!/usr/bin/env python3
import rclpy, subprocess, os, wave
from rclpy.node import Node
from std_msgs.msg import String
from piper import PiperVoice
from piper.config import SynthesisConfig

MODEL_PATH = '/home/sunrise/tts_model/zh_CN-huayan-medium.onnx'

class TTSNode(Node):
    def __init__(self):
        super().__init__('tts_node')
        self.declare_parameter('audio_sink', 'alsa_output.usb-C-Media_Electronics_Inc._USB_Audio_Device-00.analog-stereo')
        self.declare_parameter('result_topic', '/vlm_result')
        self.declare_parameter('tts_speed', 1.5)

        self.audio_sink = self.get_parameter('audio_sink').value
        result_topic = self.get_parameter('result_topic').value
        tts_speed = self.get_parameter('tts_speed').value
        self.length_scale = 1.0 / tts_speed
        self.espeak_speed = int(175 * tts_speed)  # espeak default=175wpm, scale with tts_speed

        self.sub = self.create_subscription(String, result_topic, self.callback, 10)
        self.get_logger().info(f'Piper TTS started | voice=zh_CN-huayan | speed={tts_speed}x | sink={self.audio_sink}')
        self.get_logger().info(f'Loading model: {MODEL_PATH}')
        self.voice = PiperVoice.load(MODEL_PATH)
        self.get_logger().info('Model loaded OK')

    def callback(self, msg):
        text = msg.data.strip()
        if not text:
            return
        self.get_logger().info(f'TTS: {text}')
        try:
            syn_config = SynthesisConfig(length_scale=self.length_scale)
            wav_path = '/tmp/tts_out.wav'
            with wave.open(wav_path, 'wb') as wf:
                self.voice.synthesize_wav(text, wf, syn_config=syn_config)
            subprocess.Popen(
                ['paplay', f'--device={self.audio_sink}', wav_path],
                stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
        except Exception as e:
            self.get_logger().error(f'Piper TTS failed, fallback espeak: {e}')
            subprocess.Popen(
                ['espeak-ng', '-v', 'cmn', '-s', str(self.espeak_speed), text],
                env={**os.environ, 'PULSE_SINK': self.audio_sink},
                stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)

def main(args=None):
    rclpy.init(args=args)
    node = TTSNode()
    try:
        rclpy.spin(node)
    except KeyboardInterrupt:
        pass
    finally:
        node.destroy_node()
        rclpy.shutdown()

if __name__ == '__main__':
    main()
