import 'dart:io';

import 'package:android_id/android_id.dart';
import 'package:flutter/services.dart';
import 'package:guru_platform_data/guru_platform_data.dart';
import 'package:guru_utils/datetime/datetime_utils.dart';
import 'package:guru_utils/log/log.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:device_info_plus/device_info_plus.dart';

import 'dart:ui' as ui;

import 'device_info.dart';

/// Created by Haoyi on 4/14/21
///
class DeviceUtils {
  static final DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin();

  // static final Uuid uuid = Uuid();
  static final List<SystemUiOverlay> _latestOverlays = [
    SystemUiOverlay.top,
    SystemUiOverlay.bottom
  ];

  //
  static bool? realTablet;

  static DeviceInfo? mockDeviceInfo;

  static AndroidDeviceInfo? cachedAndroidDeviceInfo;
  static IosDeviceInfo? cachedIOSDeviceInfo;

  static Future initialize() async {
    try {
      if (Platform.isAndroid) {
        cachedAndroidDeviceInfo ??= (await deviceInfoPlugin.androidInfo);
      } else if (Platform.isIOS) {
        cachedIOSDeviceInfo ??= (await deviceInfoPlugin.iosInfo);
      }
    } catch (error, stacktrace) {
      Log.w("DeviceInfo initialize error!");
    }
  }

  static Future reload() async {
    try {
      if (Platform.isAndroid) {
        cachedAndroidDeviceInfo = (await deviceInfoPlugin.androidInfo);
      } else if (Platform.isIOS) {
        cachedIOSDeviceInfo = (await deviceInfoPlugin.iosInfo);
      }
    } catch (error, stacktrace) {
      Log.w("DeviceInfo initialize error!");
    }
  }

  // static Future<String> getDeviceId() async {
  //   String deviceId = "";
  //   try {
  //     if (Platform.isAndroid) {
  //       deviceId = await deviceInfoPlugin.androidInfo.then((info) => info.androidId);
  //     } else if (Platform.isIOS) {
  //       deviceId = await deviceInfoPlugin.iosInfo.then((info) => info.identifierForVendor);
  //     }
  //   } catch (error) {}
  //
  //   if (deviceId != null && deviceId.isNotEmpty) {
  //     return deviceId;
  //   }
  //   return uuid.v4();
  // }

  static setMockDeviceInfo(DeviceInfo mock) {
    mockDeviceInfo = mock;
  }

  static LocaleInfo buildLocaleInfo() {
    final currentLocale = Platform.localeName.split('_');
    String languageCode = "";
    if (currentLocale.isNotEmpty) {
      languageCode = currentLocale[0].toLowerCase();
    }
    String countryCode = "";
    if (currentLocale.length > 1) {
      countryCode = currentLocale.last.toLowerCase();
    }
    String script = "";
    if (currentLocale.length > 2) {
      script = currentLocale[1].toLowerCase();
    }

    return LocaleInfo(languageCode, script, countryCode);
  }

  static String countryCodeToFlagEmoji(String countryCode) {
    if (countryCode.length != 2) {
      return "";
    }
    final upper = countryCode.toUpperCase();
    final code = upper == "UK" ? "GB" : upper;

    const flagOffset = 0x1F1E6;
    const asciiOffset = 0x41;

    return String.fromCharCodes([
      code.codeUnitAt(0) - asciiOffset + flagOffset,
      code.codeUnitAt(1) - asciiOffset + flagOffset
    ]);
  }

  static String currentCountryCode({String defaultCountryCode = "us"}) {
    final currentLocale = Platform.localeName.split('_');
    if (currentLocale.length > 1) {
      return currentLocale.last.toLowerCase();
    }
    return defaultCountryCode;
  }

  static void setEnabledSystemUIOverlays(List<SystemUiOverlay> overlays) {
    if (_latestOverlays != overlays) {
      // SystemChrome.setEnabledSystemUIOverlays(overlays);
      _latestOverlays.clear();
      if (overlays.isNotEmpty == true) {
        _latestOverlays.addAll(overlays);
      }
    }
  }

  /// ios 返回大版本号
  /// android 返回 SdkInt
  /// https://developer.android.com/reference/android/os/Build.VERSION_CODES
  static Future<int> getOSVersion() async {
    try {
      if (Platform.isIOS) {
        final info = await DeviceInfoPlugin().iosInfo;
        final versions = info.systemVersion.split(".") ?? [];
        return int.parse(versions[0]);
      } else if (Platform.isAndroid) {
        final info = await DeviceInfoPlugin().androidInfo;
        return info.version.sdkInt;
      }
    } catch (error, stacktrace) {
      Log.w("getOSVersion error!($error) stacktrace: $stacktrace)");
    }
    return -1;
  }

  static int peekOSVersion() {
    try {
      if (Platform.isIOS) {
        final versions = cachedIOSDeviceInfo?.systemVersion.split(".") ?? [];
        return int.parse(versions[0]);
      } else if (Platform.isAndroid) {
        return cachedAndroidDeviceInfo?.version.sdkInt ?? -1;
      }
    } catch (error, stacktrace) {
      Log.w("getOSVersion error!($error) stacktrace: $stacktrace)");
    }
    return -1;
  }

  static Future<DeviceInfo> buildDeviceInfo(
      {required String deviceId, String firebasePushToken = '', String uid = ''}) async {
    Log.d('device init');

    final _mockDeviceInfo = mockDeviceInfo;
    if (_mockDeviceInfo != null) {
      return _mockDeviceInfo..uid = uid;
    }
    // Platform special info
    String _androidId = "";
    String _deviceId = deviceId;
    String _deviceName = "";
    String _brand = "";
    String _deviceType = "";

    PackageInfo packageInfo = await PackageInfo.fromPlatform();
    if (Platform.isAndroid) {
      const androidId = AndroidId();
      var build = cachedAndroidDeviceInfo ?? await deviceInfoPlugin.androidInfo;
      _androidId = (await androidId.getId()) ?? deviceId;
      _deviceName = build.model;
      _brand = build.brand;
      _deviceType = 'android';
    } else if (Platform.isIOS) {
      var data = cachedIOSDeviceInfo ?? await deviceInfoPlugin.iosInfo;
      _deviceName = data.name ?? "";
      _brand = data.model ?? "";
      if (DeviceUtils.isTablet()) {
        _deviceType = 'iPad';
      } else {
        _deviceType = 'iPhone';
      }
    }

    String timezone = await GuruPlatformData.getLocalTimezone();
    String locale = Platform.localeName;
    List<String> localeNames = locale.split('_').toList();
    String deviceCountry = localeNames.last;
    String language = localeNames.first;

    return DeviceInfo(
      androidId: _androidId,
      appIdentifier: packageInfo.packageName,
      appVersion: packageInfo.version,
      deviceId: _deviceId,
      model: _deviceName,
      brand: _brand,
      deviceToken: firebasePushToken,
      deviceType: _deviceType,
      deviceCountry: deviceCountry,
      language: language,
      locale: locale,
      timezone: timezone,
      uid: uid,
    );
  }

  static bool isTablet() {
    if (realTablet != null) {
      return realTablet!;
    }
    final ui.Size physicalSize = ui.window.physicalSize;
    if (ui.window.devicePixelRatio < 2 &&
        (physicalSize.width >= 1000 || physicalSize.height >= 1000)) {
      return true;
    } else if (ui.window.devicePixelRatio == 2 &&
        (physicalSize.width >= 1920 || physicalSize.height >= 1920)) {
      return true;
    } else {
      return false;
    }
  }

  static Future<bool> isOutdatedTablet() async {
    if (isTablet()) {
      if (Platform.isAndroid) {
        final info = await deviceInfoPlugin.androidInfo;
        Log.d("isOutdatedTablet android: ${info.version.sdkInt}");
        return info.version.sdkInt < 24;
      } else if (Platform.isIOS) {
        final info = await deviceInfoPlugin.iosInfo;
        final versions = info.systemVersion?.split(".") ?? [];
        Log.d("isOutdatedTablet ios: $versions");
        return versions.isNotEmpty && int.parse(versions[0]) < 13;
      }
    }
    return false;
  }

  static Future<bool> isGreaterThanOrEqualIOS14() async {
    if (Platform.isIOS) {
      final info = await deviceInfoPlugin.iosInfo;
      final versions = info.systemVersion?.split(".") ?? [];
      return versions.isNotEmpty && int.parse(versions[0]) >= 14;
    } else {
      return false;
    }
  }

  static Future<String> buildContactDeviceInfo(
      {required int firstInstallTime, List<String>? extraMessages}) async {
    final StringBuffer sb = StringBuffer();
    sb.writeln("-----Please type your reply above this line-----");
    sb.writeln(
        "It would help us a lot if you could include the following information in your email:");
    sb.writeln("* Your Reason For Contacting us");
    sb.writeln("* A Screenshot or Video of the issue (If relevant or necessary)\n");
    // final accountDataStore = Injector.provide<AccountDataStore>();
    // sb.writeln("UID: ${accountDataStore.uid}");
    // final firstInstallTime =
    //     await AppProperty.getInstance().getInt(PropertyKeys.firstInstallTime, defValue: "");
    final formatTime =
        firstInstallTime > 0 ? DateTimeUtils.formatMillisecondsToStandard(firstInstallTime) : "";
    sb.writeln("Install Date: $formatTime");
    if (Platform.isAndroid) {
      var build = await deviceInfoPlugin.androidInfo;
      sb.writeln("Platform: Android");
      sb.writeln("Device: ${build.model}");
      sb.writeln("Brand: ${build.brand}");
    } else if (Platform.isIOS) {
      var data = await deviceInfoPlugin.iosInfo;
      sb.writeln("Platform: ${DeviceUtils.isTablet() ? "iPad" : "iPhone"}");
      sb.writeln("Device: ${data.name}");
      sb.writeln("Brand: ${data.model}");
    }
    final localInfo = buildLocaleInfo();
    sb.writeln("Country: ${localInfo.countryCode}");
    sb.writeln("Language: ${localInfo.languageCode}");
    sb.writeln("TimeZone: ${DateTime.now().timeZoneName}");
    // sb.writeln("HighestScore: ${StatisticManager.instance.peekBestScore().displayScore}");
    // sb.writeln("HighestBlock: ${StatisticManager.instance.peekBestBlock().displayNum}\n");
    if (extraMessages != null) {
      for (var element in extraMessages) {
        sb.writeln(element);
      }
    }
    sb.writeln("-----Please Don't Delete the info above-----");
    return sb.toString();
  }

  static final List<String> countryCodes = [
    "AD",
    "AE",
    "AF",
    "AG",
    "AI",
    "AL",
    "AM",
    "AN",
    "AO",
    "AQ",
    "AR",
    "AS",
    "AT",
    "AU",
    "AW",
    "AZ",
    "BA",
    "BB",
    "BD",
    "BE",
    "BF",
    "BG",
    "BH",
    "BI",
    "BJ",
    "BM",
    "BN",
    "BO",
    "BR",
    "BS",
    "BT",
    "BW",
    "BY",
    "BZ",
    "CA",
    "CC",
    "CD",
    "CF",
    "CG",
    "CH",
    "CI",
    "CL",
    "CM",
    "CN",
    "CO",
    "CR",
    "CU",
    "CV",
    "CX",
    "CY",
    "CZ",
    "DE",
    "DJ",
    "DK",
    "DM",
    "DO",
    "DZ",
    "EC",
    "EE",
    "EG",
    "EH",
    "ER",
    "ES",
    "ET",
    "FI",
    "FJ",
    "FK",
    "FM",
    "FO",
    "FR",
    "GA",
    "GB",
    "GD",
    "GE",
    "GG",
    "GH",
    "GI",
    "GL",
    "GM",
    "GN",
    "GQ",
    "GR",
    "GT",
    "GU",
    "GW",
    "GY",
    "HK",
    "HN",
    "HR",
    "HT",
    "HU",
    "ID",
    "IE",
    "IL",
    "IM",
    "IN",
    "IO",
    "IQ",
    "IR",
    "IS",
    "IT",
    "JE",
    "JM",
    "JO",
    "JP",
    "KE",
    "KG",
    "KH",
    "KI",
    "KM",
    "KN",
    "KP",
    "KR",
    "KW",
    "KY",
    "KZ",
    "LA",
    "LB",
    "LC",
    "LI",
    "LK",
    "LR",
    "LS",
    "LT",
    "LU",
    "LV",
    "LY",
    "MA",
    "MC",
    "MD",
    "ME",
    "MG",
    "MH",
    "MK",
    "ML",
    "MM",
    "MN",
    "MO",
    "MP",
    "MR",
    "MS",
    "MT",
    "MU",
    "MV",
    "MW",
    "MX",
    "MY",
    "MZ",
    "NA",
    "NC",
    "NE",
    "NG",
    "NI",
    "NL",
    "NO",
    "NP",
    "NR",
    "NU",
    "NZ",
    "OM",
    "PA",
    "PE",
    "PF",
    "PG",
    "PH",
    "PK",
    "PL",
    "PM",
    "PN",
    "PR",
    "PS",
    "PT",
    "PW",
    "PY",
    "QA",
    "RE",
    "RO",
    "RS",
    "RU",
    "RW",
    "SA",
    "SB",
    "SC",
    "SD",
    "SE",
    "SG",
    "SH",
    "SI",
    "SJ",
    "SK",
    "SL",
    "SM",
    "SN",
    "SO",
    "SR",
    "SS",
    "ST",
    "SV",
    "SX",
    "SY",
    "SZ",
    "TC",
    "TD",
    "TG",
    "TH",
    "TJ",
    "TK",
    "TL",
    "TM",
    "TN",
    "TO",
    "TR",
    "TT",
    "TV",
    "TW",
    "TZ",
    "UA",
    "UG",
    "US",
    "UY",
    "UZ",
    "VA",
    "VC",
    "VE",
    "VG",
    "VI",
    "VN",
    "VU",
    "WF",
    "WS",
    "YE",
    "YT",
    "ZA",
    "ZM",
    "ZW",
  ];
}
