#!/usr/bin/env python3
"""
语音唤醒检测器ROS2节点

功能：
1. 订阅ASR文字话题 (asr/text)
2. 订阅LLM状态话题 (llm/status)
3. 检测唤醒词和休眠词
4. 发布唤醒状态话题 (wake_word/status)
5. 支持拼音模糊识别
6. 根据LLM状态控制ASR订阅
"""

import rclpy
from rclpy.node import Node
from std_msgs.msg import String


class WakeWordDetector:
    """语音唤醒检测器"""

    def __init__(self):
        self.wake_words = ["优宝同学", "又把同学", "有保同学", "你好优宝"]
        self.sleep_words = ["拜拜", "再见", "休息吧", "睡觉吧"]

        try:
            from pypinyin import lazy_pinyin
            self.wake_words_pinyin = {
                word: ''.join(lazy_pinyin(word))
                for word in self.wake_words
            }
            self.sleep_words_pinyin = {
                word: ''.join(lazy_pinyin(word))
                for word in self.sleep_words
            }
        except ImportError:
            self.wake_words_pinyin = None
            self.sleep_words_pinyin = None

    def check_wake_word(self, text):
        """检查是否包含唤醒词（支持拼音模糊匹配）"""
        if not text:
            return False

        for wake_word in self.wake_words:
            if wake_word in text:
                return True

        if self.wake_words_pinyin:
            try:
                from pypinyin import lazy_pinyin
                text_pinyin = ''.join(lazy_pinyin(text))

                for wake_word, wake_pinyin in self.wake_words_pinyin.items():
                    if wake_pinyin in text_pinyin:
                        return True

                    similarity = self._calculate_similarity(wake_pinyin, text_pinyin)
                    if similarity > 0.7:
                        return True

            except Exception:
                pass

        return False

    def check_sleep_word(self, text):
        """检查是否包含休眠词（支持拼音匹配）"""
        if not text:
            return False

        for sleep_word in self.sleep_words:
            if sleep_word in text:
                return True

        if self.sleep_words_pinyin:
            try:
                from pypinyin import lazy_pinyin
                text_pinyin = ''.join(lazy_pinyin(text))
                for sleep_word in self.sleep_words:
                    sleep_pinyin = ''.join(lazy_pinyin(sleep_word))
                    if sleep_pinyin in text_pinyin:
                        return True
            except:
                pass

        return False

    def _calculate_similarity(self, s1, s2):
        """计算两个拼音字符串的相似度（编辑距离）"""
        if not s1 or not s2:
            return 0.0

        len1, len2 = len(s1), len(s2)
        dp = [[0] * (len2 + 1) for _ in range(len1 + 1)]

        for i in range(len1 + 1):
            dp[i][0] = i
        for j in range(len2 + 1):
            dp[0][j] = j

        for i in range(1, len1 + 1):
            for j in range(1, len2 + 1):
                if s1[i-1] == s2[j-1]:
                    dp[i][j] = dp[i-1][j-1]
                else:
                    dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1

        distance = dp[len1][len2]
        max_len = max(len1, len2)
        similarity = 1 - (distance / max_len) if max_len > 0 else 0

        return similarity


class WakeWordNode(Node):
    """语音唤醒检测器ROS2节点"""

    def __init__(self):
        super().__init__('wake_word_node')

        self.asr_subscriber = self.create_subscription(
            String,
            'asr/text',
            self.asr_callback,
            10
        )

        self.status_publisher = self.create_publisher(
            String,
            'wake_word/status',
            10
        )

        self.llm_status_subscriber = self.create_subscription(
            String,
            'llm/status',
            self.llm_status_callback,
            10
        )

        self.wake_detector = WakeWordDetector()
        self.is_awake = False
        self.llm_is_active = False

        self.get_logger().info('语音唤醒检测器节点初始化完成')
        self.get_logger().info('当前状态: 休眠')

    def asr_callback(self, msg):
        """处理ASR话题回调"""
        text = msg.data
        self.get_logger().info(f'收到ASR信息: {text}')

        if self.wake_detector.check_sleep_word(text):
            self.get_logger().info('检测到休眠词，进入休眠状态')
            self.is_awake = False
            self._publish_status("sleep")

        elif not self.is_awake and self.wake_detector.check_wake_word(text):
            self.get_logger().info('检测到唤醒词，进入唤醒状态')
            self.is_awake = True
            self._publish_status("wake")

    def llm_status_callback(self, msg):
        """处理LLM状态回调"""
        status = msg.data
        self.get_logger().info(f'收到LLM状态: {status}')

        if status == "active":
            self.llm_is_active = True
        elif status == "inactive":
            self.llm_is_active = False

    def _publish_status(self, status):
        """发布唤醒状态"""
        msg = String()
        msg.data = status
        self.status_publisher.publish(msg)
        self.get_logger().info(f'发布唤醒状态: {status}')


def main(args=None):
    """主函数"""
    rclpy.init(args=args)

    node = WakeWordNode()

    try:
        rclpy.spin(node)
    except KeyboardInterrupt:
        pass
    finally:
        node.destroy_node()
        rclpy.shutdown()


if __name__ == '__main__':
    main()
