import 'dart:convert';

import 'package:intl/intl.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class AppLocalizations {
  Locale locale;
  late Map<String, String> _localizedStrings;
  static Iterable<Locale> locales = <Locale>[
    const Locale(
      "vi",
      "VN",
    ),
    const Locale(
      "en",
      "US",
    )
  ];
  String _defaultPath = "lib/core/language/";

  AppLocalizations(this.locale);

  static AppLocalizations? of(BuildContext context) {
    return Localizations.of<AppLocalizations>(context, AppLocalizations);
  }

  static LocalizationsDelegate<AppLocalizations> delegate = _AppLocalizationsDelegate(locales);

  void init({List<Locale>? supportLocales, String? defaultPathI18n}) {
    if (supportLocales != null && supportLocales.length > 0) locales = supportLocales;
    if (!defaultPathI18n!.isNotEmpty) _defaultPath = defaultPathI18n;

    if (_defaultPath[_defaultPath.length - 1] != '/') _defaultPath += "/";
  }

  Future<bool> load() async {
    // set Intl
    Intl.defaultLocale = locale.languageCode;
    //Todo chỉnh phần này nếu muốn load API
    final String jsonString = await rootBundle.loadString('$_defaultPath${locale.languageCode}.json');

    final Map<String, dynamic> jsonMap = json.decode(jsonString);
    _localizedStrings = jsonMap.map((String key, dynamic value) {
      return MapEntry(key, value.toString());
    });

    return true;
  }

  //Dịch từ
  String translate(String key) {
    return _localizedStrings[key] ?? key;
  }

  String displayNumber(dynamic value) {
    if (value == null) return "";
    if (value - double.parse(value.toString()).toInt() < 1) return NumberFormat("##0.0#").format(value);
    if (value - double.parse(value.toString()).toInt() > 0) return NumberFormat("###.0#").format(value);
    return NumberFormat().format(value);
  }

  String displayScore(BuildContext context, dynamic value) {
    return displayNumber(value) + ' ' + AppLocalizations.of(context)!.translate("point").toLowerCase();
  }

  DateFormat getDefaultDateTimeFormat(
      {bool isFullTime = false, bool isDateOfWeek = false, bool isOnlyTime = false, bool isDateOfMonth = false}) {
    final String? languageCode = locale.languageCode;
    if (isFullTime) {
      return DateFormat.Hm(languageCode).add_yMd();
    } else if (isDateOfMonth) {
      return DateFormat.Hm(languageCode).addPattern('-').add_Md();
    } else if (isDateOfWeek) {
      return DateFormat.yMMMMEEEEd(languageCode);
    } else if (isOnlyTime) {
      return DateFormat.Hm(languageCode);
    } else {
      return DateFormat.yMd(languageCode);
    }
  }

  String displayDateTime(DateTime? value,
      {bool isFullTime = true, bool isDateOfWeek = false, bool isOnlyTime = false, bool isDateOfMonth = false}) {
    return value != null
        ? getDefaultDateTimeFormat(
                isFullTime: isFullTime,
                isDateOfWeek: isDateOfWeek,
                isOnlyTime: isOnlyTime,
                isDateOfMonth: isDateOfMonth)
            .format(value)
        : '';
  }

  String displayTime(DateTime value) {
    final String? languageCode = locale.languageCode;
    return DateFormat.Hm(languageCode).format(value);
  }

  //Khởi tạo Locale
  static Locale localeResolutionCallback(Locale? locale, Iterable<Locale> supportedLocales) {
    for (final Locale supportedLocale in supportedLocales) {
      if (locale != null &&
          supportedLocale.languageCode == locale.languageCode &&
          supportedLocale.countryCode == locale.countryCode) {
        return supportedLocale;
      }
    }
    return supportedLocales.first;
  }

  Future<bool> changeLocale(BuildContext context, Locale locale) {
    AppLocalizations.of(context)!.locale = locale;
    Intl.defaultLocale = locale.languageCode;
    return AppLocalizations.of(context)!.load();
  }

  // Convert tiền
  String displayCurrency(double price) {
    final String? languageCode = locale.languageCode;
    final String curency = NumberFormat.simpleCurrency(locale: languageCode).format(price);
    return curency;
  }
}

class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
  final Iterable<Locale> _supportLocale;

  _AppLocalizationsDelegate(this._supportLocale);

  @override
  bool isSupported(Locale locale) {
    // Include all of your supported language codes here
    return _supportLocale.map((e) => e.languageCode).contains(locale.languageCode);
  }

  @override
  Future<AppLocalizations> load(Locale locale) async {
    // AppLocalizations class is where the JSON loading actually runs
    final AppLocalizations localizations = AppLocalizations(locale);
    await localizations.load();
    return localizations;
  }

  @override
  bool shouldReload(_AppLocalizationsDelegate old) => false;
}
