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

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_text_detect_area/flutter_text_detect_area.dart';
import 'package:flutter_translate/ads/interstitial_ad_manage.dart';
import 'package:flutter_translate/common/components/speak_alert.dart';
import 'package:flutter_translate/common/hive/history_data.dart';
import 'package:flutter_translate/common/utils/bot_toast.dart';
import 'package:flutter_translate/common/utils/log_utils.dart';
import 'package:flutter_translate/common/utils/number_utils.dart';
import 'package:flutter_translate/common/utils/object_utils.dart';
import 'package:flutter_translate/common/utils/permission_utils.dart';
import 'package:flutter_translate/common/utils/shared_util.dart';
import 'package:flutter_translate/generated/assets.dart';
import 'package:flutter_translate/global/app_lifecycle_reactor.dart';
import 'package:flutter_translate/global/app_tracking_transparency_manager.dart';
import 'package:flutter_translate/manager/speech_convert.dart';
import 'package:flutter_translate/manager/translate.dart';
import 'package:flutter_translate/manager/tts.dart';
import 'package:flutter_translate/model/history_model.dart';
import 'package:flutter_translate/model/language_model.dart';
import 'package:flutter_translate/model/scene_model.dart';
import 'package:flutter_translate/pages/home/components/photo_picker.dart';
import 'package:flutter_translate/router/get_gages.dart';
import 'package:get/get.dart';
import 'package:image_picker/image_picker.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:speech_to_text/speech_recognition_result.dart';

class HomeController extends GetxController {
  static HomeController get to => Get.find<HomeController>();

  final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey();

  var versionName = ''.obs;

  var options = ['Privacy Policy', 'User Agreement', 'Color Setting'];

  var lastWords = '';

  var fromLanguage = Rx<LanguageModel>(
    LanguageModel(code: 'en', name: 'English'),
  );
  var toLanguage = Rx<LanguageModel>(
    LanguageModel(code: 'zh-cn', name: 'Chinese (Simplified)'),
  );

  var fromScene = Rx<String>("loading");
  var toScene = Rx<String>("loading");

  RxBool isPlayingFrom = false.obs;
  RxBool isPlayingTo = false.obs;

  RxInt appColor = 0xff529F2D.obs;

  final languageModels = <LanguageModel>[
    LanguageModel(code: 'zh-cn', name: 'Chinese (Simplified)'),
    LanguageModel(code: 'ar', name: 'Arabic'),
    LanguageModel(code: 'bn', name: 'Bengali'),
    LanguageModel(code: 'en', name: 'English'),
    LanguageModel(code: 'fr', name: 'French'),
    LanguageModel(code: 'de', name: 'German'),
    LanguageModel(code: 'hi', name: 'Hindi'),
    LanguageModel(code: 'ja', name: 'Japanese'),
    LanguageModel(code: 'jv', name: 'Javanese'),
    LanguageModel(code: 'ko', name: 'Korean'),
    LanguageModel(code: 'pt', name: 'Portuguese'),
    LanguageModel(code: 'pa', name: 'Punjabi'),
    LanguageModel(code: 'ru', name: 'Russian'),
    LanguageModel(code: 'es', name: 'Spanish'),
  ];
  var historyList = <HistoryModel>[].obs;

  @override
  void onInit() {
    super.onInit();
    AppTrackingTransparencyManager().requestATT();
    AppLifecycleReactor().listenToAppStateChanges();

    appColor.value = SharedUtil.getInstance().get<int>("appColor") ?? 0xff554281;
    _getAppVersion();
  }

  @override
  void onReady() {
    super.onReady();
    initData();
    initHistoryList();
  }

  @override
  void onClose() {
    AppLifecycleReactor().appLifecycleListener?.dispose();
    super.onClose();
  }

  void initHistoryList() {
    historyList.value = HistoryData().findAll().reversed.toList();
  }

  Future<void> initData() async {
    LanguageModel fromModel = Translate().fromLanguageEntity.value;
    LanguageModel toModel = Translate().toLanguageEntity.value;

    LanguageModel? f =
        languageModels.firstWhereOrNull((e) => e.code == fromModel.code);
    if (f != null) fromLanguage.value = f;

    LanguageModel? t = languageModels.firstWhereOrNull((e) => e.code == toModel.code);
    if (t != null) toLanguage.value = t;

    var data = jsonDecode(await rootBundle.loadString(Assets.jsonScene));

    if (data != null && data is List) {
      var sceneTypeList = data.map((e) => SceneModel.fromMap(e)).toList();
      if (sceneTypeList.isNotEmpty) {
        var x = NumberUtils.getRandomNumber(0, sceneTypeList.length);
        SceneModel entity = sceneTypeList[x];
        if (entity.sceneList != null && entity.sceneList!.isNotEmpty) {
          var y = NumberUtils.getRandomNumber(0, entity.sceneList!.length);
          fromScene.value = _getSentence(true, entity.sceneList![y]);
          toScene.value = _getSentence(false, entity.sceneList![y]);
        }
      }
    }
  }

  /// 获取版本号
  void _getAppVersion() async {
    final packageInfo = await PackageInfo.fromPlatform();
    versionName.value = 'version number ${packageInfo.version}';
  }

  void openHomeDrawer() {
    scaffoldKey.currentState?.openDrawer();
  }

  void clickItem(int index) {
    Log.d(index);
    if (index == 2) {
      Get.toNamed(GetPages.colorSetting);
    } else {
      Get.toNamed(GetPages.webView, arguments: {
        'title': options[index],
        'url': index == 0
            ? 'https://trans-globe.mystrikingly.com/privacy'
            : 'https://trans-globe.mystrikingly.com/terms',
      });
    }
    scaffoldKey.currentState?.closeDrawer();
  }

  String _getSentence(bool isFrom, SceneList sceneList) {
    List keys = sceneList.toMap().keys.toList();
    List values = sceneList.toMap().values.toList();
    int index = keys.indexWhere(
        (e) => e == (isFrom ? fromLanguage.value.name : toLanguage.value.name));
    if (index != -1) {
      return values[index];
    }
    return 'loading';
  }

  void textConvertVoice(bool isFrom) async {
    isPlayingTo.value = false;
    isPlayingFrom.value = false;
    if (isFrom) {
      isPlayingFrom.value = true;
      await Tts().voiceTranslator(fromScene.value, fromLanguage.value.code);
      isPlayingFrom.value = false;
    } else {
      isPlayingTo.value = true;
      await Tts().voiceTranslator(toScene.value, toLanguage.value.code);
      isPlayingTo.value = false;
    }
  }

  void sceneCategory() {
    Get.toNamed(GetPages.sceneCategory);
  }

  Future photos() async {
    Get.bottomSheet(
      isScrollControlled: true,
      PhotoPicker(
        funCamera: () async {
          await PermissionUtils.checkPermission(
            [Permission.camera],
          ).then((res) {
            if (!res) return;
            _openCameraGallery(ImageSource.camera);
          });
        },
        funGallery: () async {
          Permission permission = Permission.photos;
          await PermissionUtils.checkPermission(
            [permission],
          ).then((res) {
            if (!res) return;
            _openCameraGallery(ImageSource.gallery);
          });
        },
      ),
    );
  }

  void face2face() {
    InterstitialAdManager().showAdIfReady(
      InterstitialAdManager().adIds[2],
      onTap: () async {
        bool micResult = await PermissionUtils.checkPermission(
          [Permission.microphone],
        );
        if (!micResult) return;
        if (Platform.isIOS) {
          bool speechResult = await PermissionUtils.checkPermission(
            [Permission.speech],
          );
          if (!speechResult) return;
        }
        Get.toNamed(GetPages.faceToFace);
      },
    );
  }

  void history() {
    Get.toNamed(GetPages.history);
  }

  void translator() {
    Get.toNamed(GetPages.translator);
  }

  Future speak() async {
    bool micResult =
        await PermissionUtils.checkPermission([Permission.microphone]);
    if (!micResult) return;
    if (Platform.isIOS) {
      bool speechResult =
          await PermissionUtils.checkPermission([Permission.speech]);
      if (!speechResult) return;
    }
    await Get.dialog(
      barrierDismissible: true,
      useSafeArea: false,
      SpeakAlert(
        isListening: SpeechConvert().isListening,
        onTap: () async {
          if (!SpeechConvert().hasSpeech) {
            await SpeechConvert().init();
          }
          if (SpeechConvert().hasSpeech) {
            if (SpeechConvert().isListening.value) {
              _translatedText();
            } else {
              SpeechConvert().start(
                Translate().fromLanguageEntity.value.code,
                (SpeechRecognitionResult result) {
                  Log.d('识别结果：${result.recognizedWords}');
                  lastWords = result.recognizedWords;
                },
              );
            }
          } else {
            Get.back();
            toast('Speech not available');
          }
        },
      ),
    );
    if (Get.isDialogOpen != null && !Get.isDialogOpen!) {
      SpeechConvert().stop(showLoading: false);
    }
  }

  void _translatedText() {
    if (ObjectUtils.isEmpty(lastWords)) {
      toast('No text recognized');
      return;
    }
    Get.back();
    Get.toNamed(
      GetPages.translateText,
      arguments: {"sourceText": lastWords},
    );
  }

  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)) {
                toast(
                  'Selected area should be able to crop image with at least 32 width and height.',
                );
              }
            },
          ))?.then(
        (onValue) {
          InterstitialAdManager().showAdIfReady(
            InterstitialAdManager().adIds[3],
            onTap: () {
              if (ObjectUtils.isEmpty(detectedValue)) {
                toast('No text recognized');
                return;
              }
              Get.toNamed(
                GetPages.translateText,
                arguments: {"sourceText": detectedValue},
              );
            },
          );
        },
      );
    }
  }

  void removeHistoryByIndex(int index) {
    // 计算原始列表中的对应索引
    int indexToRemoveFromDb = HistoryData().findAll().length - 1 - index;
    historyList.removeAt(indexToRemoveFromDb);
    HistoryData().remove(indexToRemoveFromDb);
  }

  void historyTranslate(HistoryModel historyModel) {
    Get.toNamed(
      GetPages.translateText,
      arguments: {
        'isHistory': true,
        'sourceText': historyModel.sourceText,
        'targetText': historyModel.targetText,
        'fromLanguageName': historyModel.sourceLanguageName,
        'toLanguageName': historyModel.targetLanguageName,
        'fromLanguageCode': historyModel.sourceLanguageCode,
        'toLanguageCode': historyModel.targetLanguageCode,
      },
    );
  }
}
