import 'dart:async';
import 'package:flutter/services.dart';

import 'vosk_wakeword_error.dart';
import 'model/recognition_event.dart';

/// Vosk 唤醒词插件的主接口 (单例模式)
///
/// 这个类负责向原生代码发送指令，并通过 Stream 接收识别事件。
/// 所有的音频采集和处理都在原生端完成。
class FlutterVoskWakeword {
  // 私有构造函数
  FlutterVoskWakeword._internal();
  // 获取唯一实例
  static FlutterVoskWakeword get instance => _instance;
  // 静态、唯一的实例
  static final FlutterVoskWakeword _instance = FlutterVoskWakeword._internal();

  // Factory 构造函数返回唯一实例
  factory FlutterVoskWakeword() => _instance;

  static const MethodChannel _methodChannel = MethodChannel('flutter_vosk_wakeword/methods');
  static const EventChannel _eventChannel = EventChannel('flutter_vosk_wakeword/events');

  Stream<RecognitionEvent>? _recognitionStream;

  /// 监听识别事件的流
  Stream<RecognitionEvent> get recognitionStream {
    _recognitionStream ??= _eventChannel
        .receiveBroadcastStream()
        .map((event) => RecognitionEvent.fromJson(Map<String, dynamic>.from(event)));
    return _recognitionStream!;
  }

  /// 初始化 Vosk 引擎和模型
  Future<bool> initialize({
    // required String modelPath,
    required List<String> wakeWords,
  }) async {
    try {
      final result = await _methodChannel.invokeMethod<bool>('initialize', {
        // 'modelPath': modelPath,
        'wakeWords': wakeWords,
      });
      return result ?? false;
    } on PlatformException catch (e) {
      throw voskStatusToException(e.code, e.message);
    }
  }

  /// 开始监听
  Future<bool> start() async {
    try {
      return await _methodChannel.invokeMethod<bool>('start') ?? false;
    } on PlatformException catch (e) {
      throw voskStatusToException(e.code, e.message);
    }
  }

  /// 停止监听
  Future<bool> stop() async {
    try {
      return await _methodChannel.invokeMethod<bool>('stop') ?? false;
    } on PlatformException catch (e) {
      throw voskStatusToException(e.code, e.message);
    }
  }

  /// 释放所有原生资源
  Future<bool> dispose() async {
    try {
      return await _methodChannel.invokeMethod<bool>('dispose') ?? false;
    } on PlatformException catch (e) {
      throw voskStatusToException(e.code, e.message);
    }
  }
}