import 'package:flutter_translate/common/utils/bot_toast.dart';
import 'package:flutter_translate/common/utils/log_utils.dart';
import 'package:get/get.dart';
import 'package:speech_to_text/speech_recognition_error.dart';
import 'package:speech_to_text/speech_to_text.dart';

class SpeechConvert {
  static final SpeechConvert _instance = SpeechConvert._();

  SpeechConvert._();

  factory SpeechConvert() {
    return _instance;
  }

  final _speechToText = SpeechToText();

  var isListening = false.obs;
  var hasSpeech = false;

  Future<void> init() async {
    try {
      loading();
      hasSpeech = await _speechToText.initialize(
        onStatus: _statusListener,
        onError: _errorListener,
      );
      dismiss();
      _speechToText.statusListener ??= _statusListener;
      _speechToText.errorListener ??= _errorListener;
    } catch (e) {
      Log.d('Speech recognition failed: ${e.toString()}');
    }
  }

  Future<void> start(String localeId, SpeechResultListener onResult) async {
    loading();
    try {
      await _speechToText.listen(
        onResult: onResult,
        localeId: localeId,
        listenFor: const Duration(minutes: 30),
        pauseFor: const Duration(minutes: 3),
        listenOptions: SpeechListenOptions(
          cancelOnError: true,
          autoPunctuation: true,
          listenMode: ListenMode.dictation,
        ),
      );
      dismiss();
    } catch (e) {
      if (e.runtimeType == ListenFailedException) {
        Log.d('speechToText.listen：${(e as ListenFailedException).message}');
      } else {
        Log.d('speechToText.listen：${e.toString()}');
      }
      toast('The current language does not support speech recognition');
    }
  }

  void _statusListener(String status) {
    Log.d('状态：$status');
    isListening.value = status == 'listening';
  }

  void _errorListener(SpeechRecognitionError error) {
    Log.d(
      'Received error status: $error, listening: ${_speechToText.isListening}',
    );
    toast('Speech recognition failed: ${error.errorMsg}');
  }

  Future<void> stop({bool? showLoading}) async {
    if (isListening.value) {
      loading(show: showLoading??true);
      await _speechToText.stop();
      dismiss();
    }
  }
}
