import 'dart:convert';
import 'dart:io';

import 'package:flutter/services.dart';
import 'package:flutter_text_detect_area/flutter_text_detect_area.dart';
import 'package:get/get.dart';
import 'package:image_picker/image_picker.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:speech_to_text/speech_recognition_result.dart';
import 'package:trans_lark/entity/language_entity.dart';
import 'package:trans_lark/entity/scene_entity.dart';
import 'package:trans_lark/generated/assets.dart';
import 'package:trans_lark/global/app_tracking_authorization_manager.dart';
import 'package:trans_lark/global/flutter_tts_manager.dart';
import 'package:trans_lark/global/speech_to_text_manager.dart';
import 'package:trans_lark/global/translate_manager.dart';
import 'package:trans_lark/page/settings/settings_view.dart';
import 'package:trans_lark/router/router.dart';
import 'package:trans_lark/util/device_info_util.dart';
import 'package:trans_lark/util/log_print.dart';
import 'package:trans_lark/util/num_util.dart';
import 'package:trans_lark/util/obj_util.dart';
import 'package:trans_lark/util/permission_util.dart';
import 'package:trans_lark/widget/base_easyloading.dart';
import 'package:trans_lark/widget/photo_picker_bottom_sheet.dart';
import 'package:trans_lark/widget/speak_dialog.dart';

class HomeLogic extends GetxController {
  static HomeLogic get to => Get.find<HomeLogic>();
  var lastWords = '';

  var fromLanguage = Rx<LanguageEntity?>(null);
  var toLanguage = Rx<LanguageEntity?>(null);
  var fromStr = Rx<String?>(null);
  var toStr = Rx<String?>(null);

  @override
  void onInit() {
    super.onInit();
    AppTrackingAuthorizationManager().requestTrackingAuthorization();
  }

  @override
  void onReady() {
    super.onReady();
    getDailyQuote();
  }

  Future<void> getDailyQuote() async {
    LanguageEntity fromLanguageEntity =
        TranslateManager().fromLanguageEntity.value;
    LanguageEntity toLanguageEntity = TranslateManager().toLanguageEntity.value;
    var languageScene = <LanguageEntity>[
      LanguageEntity(languageCode: 'ar', languageName: 'Arabic'),
      LanguageEntity(languageCode: 'bn', languageName: 'Bengali'),
      LanguageEntity(
          languageCode: 'zh-cn', languageName: 'Chinese (Simplified)'),
      LanguageEntity(languageCode: 'en', languageName: 'English'),
      LanguageEntity(languageCode: 'fr', languageName: 'French'),
      LanguageEntity(languageCode: 'de', languageName: 'German'),
      LanguageEntity(languageCode: 'hi', languageName: 'Hindi'),
      LanguageEntity(languageCode: 'ja', languageName: 'Japanese'),
      LanguageEntity(languageCode: 'jv', languageName: 'Javanese'),
      LanguageEntity(languageCode: 'ko', languageName: 'Korean'),
      LanguageEntity(languageCode: 'pt', languageName: 'Portuguese'),
      LanguageEntity(languageCode: 'pa', languageName: 'Punjabi'),
      LanguageEntity(languageCode: 'ru', languageName: 'Russian'),
      LanguageEntity(languageCode: 'es', languageName: 'Spanish'),
    ];
    fromLanguage.value = languageScene.firstWhereOrNull(
          (e) => e.languageCode == fromLanguageEntity.languageCode,
        ) ??
        LanguageEntity(
          languageCode: 'en',
          languageName: 'English',
        );
    toLanguage.value = languageScene.firstWhereOrNull(
          (e) => e.languageCode == toLanguageEntity.languageCode,
        ) ??
        LanguageEntity(
          languageCode: 'zh-cn',
          languageName: 'Chinese (Simplified)',
        );
    // final f = NumUtil.getRandomNumber(0, languageScene.length);
    // final t = NumUtil.getRandomNumberExcludingCurrent(0, languageScene.length, f);
    // fromLanguage.value = languageScene[f];
    // toLanguage.value = languageScene[t];

    var data =
        jsonDecode(await rootBundle.loadString(Assets.jsonTranslationScene));
    if (data != null && data is List) {
      var sceneTypeList = data.map((e) => SceneEntity.fromMap(e)).toList();
      if (sceneTypeList.isNotEmpty) {
        var x = NumUtil.getRandomNumber(0, sceneTypeList.length);
        SceneEntity entity = sceneTypeList[x];
        if (entity.sceneList != null && entity.sceneList!.isNotEmpty) {
          var y = NumUtil.getRandomNumber(0, entity.sceneList!.length);

          fromStr.value = _getSentence(true, entity.sceneList![y]);
          toStr.value = _getSentence(false, entity.sceneList![y]);
        }
      }
    }
  }

  String _getSentence(bool isFrom, SceneList item) {
    List keys = item.toMap().keys.toList();
    int index = 0;
    for (var i = 0; i < keys.length; ++i) {
      var e = keys[i];
      if (e ==
          (isFrom
              ? fromLanguage.value?.languageName
              : toLanguage.value?.languageName)) {
        index = i;
        break;
      }
    }
    if (item.toMap().values.toList()[index] != null) {
      return item.toMap().values.toList()[index];
    }
    return 'loading';
  }

  void translatorTtsPlay(bool isFrom) {
    if (fromLanguage.value != null && toLanguage.value != null) {
      FlutterTtsManager().translatorTtsPlay(
        isFrom ? fromStr.value! : toStr.value!,
        isFrom
            ? fromLanguage.value!.languageCode
            : toLanguage.value!.languageCode,
      );
    }
  }

  void openSettings() {
    Get.bottomSheet(
      isScrollControlled: true,
      SettingsView(),
    );
  }

  void openSceneType() {
    Get.toNamed(GetRouter.sceneType);
  }

  Future<void> onTapPhotos() async {
    Get.bottomSheet(
      isScrollControlled: true,
      PhotoPickerBottomSheet(
        funCamera: () async {
          bool result =
              await PermissionUtil.checkPermission([Permission.camera]);
          if (!result) return;
          _openCameraGallery(ImageSource.camera);
        },
        funGallery: () async {
          Permission permission = Permission.photos;
          if (Platform.isAndroid) {
            int sdkInt = await DeviceInfoUtil.getAndroidSDKInt();
            if (sdkInt <= 32) {
              permission = Permission.storage;
            } else {
              permission = Permission.photos;
            }
          }
          bool result = await PermissionUtil.checkPermission([permission]);
          if (!result) return;
          _openCameraGallery(ImageSource.gallery);
        },
      ),
    );
  }

  Future<void> _openCameraGallery(ImageSource source) async {
    String detectedValue = "";
    final ImagePicker picker = ImagePicker();
    final XFile? photo = await picker.pickImage(source: source);
    if (photo != null) {
      Get.to(() => SelectImageAreaTextDetect(
            detectOnce: true,
            enableImageInteractions: true,
            imagePath: photo.path,
            onDetectText: (v) {
              if (v is String) {
                detectedValue = v;
              }
              if (v is List) {
                int counter = 0;
                for (var element in v) {
                  detectedValue += "$counter. \t\t $element \n\n";
                  counter++;
                }
              }
            },
            onDetectError: (error) {
              ///This error will occurred in Android only while user will try to crop image at max zoom level then ml kit will throw max 32 height/width exception
              if (error is PlatformException &&
                  (error.message?.contains(
                          "InputImage width and height should be at least 32!") ??
                      false)) {
                BaseEasyLoading.toast(
                    'Selected area should be able to crop image with at least 32 width and height.');
              }
            },
          ))?.then(
        (onValue) {
          if (ObjUtil.isEmpty(detectedValue)) {
            BaseEasyLoading.toast('No text recognized');
            return;
          }
          Get.toNamed(
            GetRouter.translateResult,
            arguments: {"sourceText": detectedValue},
          );
        },
      );
    }
  }

  Future<void> onTapSpeak() async {
    bool micResult =
        await PermissionUtil.checkPermission([Permission.microphone]);
    if (!micResult) return;
    if (Platform.isIOS) {
      bool speechResult =
          await PermissionUtil.checkPermission([Permission.speech]);
      if (!speechResult) return;
    }
    await Get.dialog(
      barrierDismissible: true,
      useSafeArea: false,
      SpeakDialog(
        isListening: SpeechToTextManager().isListening,
        onTap: () async {
          if (!SpeechToTextManager().hasSpeech) {
            await SpeechToTextManager().initSpeech();
          }
          if (SpeechToTextManager().hasSpeech) {
            if (SpeechToTextManager().isListening.value) {
              _openTranslatorResultPage();
            } else {
              SpeechToTextManager().startListening(
                  TranslateManager().fromLanguageEntity.value.languageCode,
                  _onSpeechResult);
            }
          } else {
            Get.back();
            BaseEasyLoading.toast('Speech not available');
          }
        },
      ),
    );
    if (Get.isDialogOpen != null && !Get.isDialogOpen!) {
      SpeechToTextManager().stopListening();
    }
  }

  void _onSpeechResult(SpeechRecognitionResult result) {
    LogPrint.d('识别结果：${result.recognizedWords}');
    lastWords = result.recognizedWords;
  }

  void _openTranslatorResultPage() {
    if (ObjUtil.isEmpty(lastWords)) {
      BaseEasyLoading.toast('No text recognized');
      return;
    }
    Get.back();
    Get.toNamed(
      GetRouter.translateResult,
      arguments: {"sourceText": lastWords},
    );
  }

  void openTranslate() {
    Get.toNamed(GetRouter.translate);
  }

  Future<void> openFaceToFace() async {
    bool micResult =
        await PermissionUtil.checkPermission([Permission.microphone]);
    if (!micResult) return;
    if (Platform.isIOS) {
      bool speechResult =
          await PermissionUtil.checkPermission([Permission.speech]);
      if (!speechResult) return;
    }
    Get.toNamed(GetRouter.faceToFace);
  }

  void openTranslateHistory() {
    Get.toNamed(GetRouter.translateHistory);
  }
}
