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

class AppLocalizations {
  final Locale locale;
  final Map<String, String> _strings;

  AppLocalizations(this.locale, this._strings);

  String get(String key) => _strings[key] ?? key;

  String getString(String key, {Map<String, String>? args}) {
    var value = _strings[key] ?? key;
    if (args != null) {
      for (final entry in args.entries) {
        value = value.replaceAll('\${${entry.key}}', entry.value);
      }
    }
    return value;
  }

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

  static Future<AppLocalizations> load(Locale locale) async {
    String langCode;
    if (locale.languageCode == 'zh') {
      langCode = locale.countryCode == 'TW' ? 'zh_TW' : 'zh_CN';
    } else {
      langCode = locale.languageCode;
    }
    final path = 'assets/i18n/$langCode.json';
    final jsonStr = await rootBundle.loadString(path);
    final raw = jsonDecode(jsonStr) as Map<String, dynamic>;
    final flat = <String, String>{};
    void flatten(Map<String, dynamic> map) {
      for (final entry in map.entries) {
        if (entry.value is Map<String, dynamic>) {
          flatten(entry.value as Map<String, dynamic>);
        } else {
          flat[entry.key] = entry.value.toString();
        }
      }
    }
    flatten(raw);
    return AppLocalizations(locale, flat);
  }

  static const LocalizationsDelegate<AppLocalizations> delegate =
      _AppLocalizationsDelegate();
}

class _AppLocalizationsDelegate
    extends LocalizationsDelegate<AppLocalizations> {
  const _AppLocalizationsDelegate();

  @override
  bool isSupported(Locale locale) => ['zh', 'en'].contains(locale.languageCode);

  @override
  Future<AppLocalizations> load(Locale locale) => AppLocalizations.load(locale);

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