import 'package:fis_common/logger/logger.dart';
import 'package:fis_i18n/i18n.dart';
import 'package:fis_theme/theme.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flyinsono/architecture/states/states.dart';
import 'package:flyinsono/architecture/states/types.dart';
import 'package:flyinsono/architecture/utils/prompt_box.dart';
import 'package:flyinsono/architecture/utils/web.dart';
import 'package:get/get.dart';

/// 应用状态
class AppState extends StateModuleBase {
  AppState() {
    _locale = Locale(systemLocale.languageCode, systemLocale.countryCode).obs;
    _setSystemLocaleOnChange();
    logger.i('AppState ctor: system locale: $_locale.');
  }

  var _busy = false.obs;
  var _networkRetryCount = 0.obs;
  final _enableVidLoopPlayback = RxBool(false);
  Rx<bool> _isWin7 = Rx(false);

  /// busy状态锁，在函数调用链的最外层设置，防止中间busy被多次变更
  bool lockBusy = false;

  /// 程序处理是否忙碌中
  bool get busy => _busy.value;
  set busy(bool v) {
    if (lockBusy) {
      return;
    }
    _busy.value = v;
    if (v) {
      PromptBox.loading();
    } else {
      PromptBox.dismiss();
    }
  }

  /// 网络连接重试次数
  int get networkRetryCount => _networkRetryCount.value;
  set networkRetryCount(int v) {
    _networkRetryCount.value = v;
  }

  void setBusy(String text) {
    _busy.value = true;
    PromptBox.loading(text);
  }

  void cancelBusy() => busy = false;

  Locale get systemLocale => WidgetsBinding.instance.window.locale;

  late Rx<Locale> _locale;

  /// 当前语言
  Locale get locale => _locale.value;

  /// 当前语言是否中文
  bool get isCurrChinese => locale.languageCode.toLowerCase() == "zh";

  final _isFollowSystemLocale = true.obs;

  /// 是否跟随系统语言
  bool get isFollowSystemLocale => _isFollowSystemLocale.value;

  ///是否使用新标签页
  bool enableNewTab = kDebugMode ? false : true;

  ///是否启用调试输入框
  bool isOpenDebugBox = false;

  /// 是否开启Vid循环播放
  bool get enableVidLoopPlayback => _enableVidLoopPlayback.value;
  set enableVidLoopPlayback(bool val) {
    if (val != _enableVidLoopPlayback.value) {
      _enableVidLoopPlayback.value = val;
      Store.persistent();
    }
  }

  ///是否win7环境
  bool get isWin7 => _isWin7.value;
  set isWin7(bool v) => _isWin7.value = v;

  /// 更新语言
  ///
  /// [value] 语言
  ///
  /// [updateApp] 是否更新APP UI
  ///
  /// [saveImmediately] 是否立即保存（持久化）
  Future<void> updateLocale(
    Locale value, {
    bool updateApp = true,
    bool saveImmediately = false,
  }) async {
    try {
      logger.i("Update locale: $value, Follow system: $isFollowSystemLocale.");
      // 只匹配 langCode和CountryCode，ScriptCode无视
      _locale(Locale(value.languageCode, value.countryCode));
      if (locale != FI18n.ins.currentBook.locale) {
        if (updateApp) {
          final matchLocale = await FI18n.ins.switchLanguage(locale);
          logger.i('FI18n switch language, match locale is $matchLocale');
          //await FTheme.ins.reload();
          await AppWebUtils.retranslateTitle();
        }
      }
      // 用户修改语言后无需跟随系统
      _isFollowSystemLocale.value = false;
      if (saveImmediately) {
        await Store.persistent();
      }
    } catch (e) {
      logger.e('AppState updateLocale ex:', e);
    }
  }

  ///设置APP语言根据操作系统语言变化而变化

  Future<void> setFollowSystemLocale(bool isFollow, [Locale? locale]) async {
    _isFollowSystemLocale.value = isFollow;
    Locale nextLocale = systemLocale;
    if (isFollow) {
      if (!FI18n.ins.supportedLocales
          .any((x) => x.languageCode == nextLocale.languageCode)) {
        nextLocale = ENGLISH_LOCALE;
      }
    } else {
      if (locale == null)
        throw Exception(
            "AppState setFollowSystemLocale error: Locale is required when isFollowSystemLocale equals false.");
      nextLocale = locale;
    }
    await updateLocale(nextLocale, saveImmediately: true);
  }

  @override
  Future<void> acceptPersistenceJson(Map<String, dynamic> map) async {
    map.pickPersistentProp(
      'isFollowSystemLocale',
      (x) => _isFollowSystemLocale.value = x != false,
    );

    if (!isFollowSystemLocale) {
      map.pickPersistentProp('locale', (x) {
        if (x is List && x.length == 2) {
          final locale = Locale(x[0], x[1]);
          logger.i("acceptPersistenceJson: $locale");
          _locale(locale);
        }
      });
    }

    map.pickPersistentProp(
        'enableVidLoopPlayback', (x) => enableVidLoopPlayback = x);
  }

  @override
  Map<String, dynamic> toPersistenceJson() {
    return {
      "locale": [locale.languageCode, locale.countryCode],
      "isFollowSystemLocale": isFollowSystemLocale,
      "enableVidLoopPlayback": enableVidLoopPlayback,
    };
  }

  void _setSystemLocaleOnChange() {
    final win = WidgetsBinding.instance.window;
    final VoidCallback? originLocaleChange = win.onLocaleChanged;
    win.onLocaleChanged = () async {
      logger.i('window.onLocaleChanged, current system locale: $systemLocale');
      if (isFollowSystemLocale) {
        await updateLocale(systemLocale);
      }
      originLocaleChange?.call();
    };
  }
}
