import 'dart:math';
import 'package:intl/intl.dart';
import 'package:road24_mobile/model/utils/Config.dart';
import 'package:translit/translit.dart';

extension monthReplacer on String {
  String monthReplacement() {
    return this
        .replaceAll("ян", "янв")
        .replaceAll("иын", "июн")
        .replaceAll("маы", "мая")
        .replaceAll("иыл", "июл")
        .replaceAll("ийл", "июл")
        .replaceAll("ноы", "нояб")
        .replaceAll("ной", "нояб");
  }
}

extension errorString on String {
  String getErrorText() {
    const start = "[";
    const end = "]";
    final regex = RegExp(r'\d+');
    String errorCode = regex.allMatches(this).map((m) => m.group(0)).toString();
    final startIndex = this.indexOf(start);
    final endIndex = this.indexOf(end, startIndex + start.length);

    return this.substring(startIndex + start.length, endIndex) + " $errorCode";
  }
}

extension formatDate on String {
  String? toFormatDate() {
    if (this.isEmpty) return null;
    DateTime date;
    try {
      try {
        date = DateTime.parse(this).toLocal();
      } catch (_) {
        var americanFormat = DateFormat('MM/dd/yy hh:mm:ss a');
        date = americanFormat.parse(this);
      }
      if (Config.language == 'oz') {
        return DateFormat('dd-MMM yyyy', 'uz').format(date).toString();
      } else if (Config.language == 'uz') {
        print("kiril");
        return DateFormat('dd-MMM yyyy', 'uz')
            .format(date)
            .toString()
            .toKrill()
            .monthReplacement();
      } else
        return DateFormat('dd-MMM yyyy', Config.language)
            .format(date)
            .toString()
            .monthReplacement();
    } catch (_) {
      return this;
    }
  }
}

extension dateToString on DateTime {
  String dateToStr() {
    // if (this.is ) return null;
    return (Config.language == 'oz')
        ? DateFormat('dd-MMM yyyy', "uz"
                // Config
                //     .language
                )
            .format(this)
        : Translit()
            .unTranslit(source: DateFormat('dd-MMM yyyy', "ru").format(this));
  }
}

extension getUnicodeString on String {
  String getUnicodedText() {
    Map<String, String> unicodeMap = {
      '0': '\u2070',
      '1': '\u00B9',
      '2': '\u00B2',
      '3': '\u00B3',
      '4': '\u2074',
      '5': '\u2075',
      '6': '\u2076',
      '7': '\u2077',
      '8': '\u2078',
      '9': '\u2079',
    };

    String text = "";

    if (this.split('^').length == 2) {
      this.split('^')[1].runes.forEach((element) {
        text = this.split('^')[0];
        text = text + unicodeMap[String.fromCharCode(element)]!;
      });
    } else {
      text = this;
    }

    return text;
  }
}

extension KrillLatinSimilarity on String {
  double similarity(
    String text, {
    bool krillLatin = true,
    bool lowerUpper = true,
  }) {
    String longer = this;
    String shorter = text;
    if (lowerUpper) {
      longer = longer.toLowerCase();
      shorter = shorter.toLowerCase();
    }
    if (krillLatin) {
      longer = longer.toLatin();
      shorter = shorter.toLatin();
    }
    if (this.length < text.length) {
      longer = text;
      shorter = this;
    }
    if (longer.length == 0) return 1.0;
    return (longer.length - _editDistance(longer, shorter)) / longer.length;
  }

  String toKrill() {
    return this
        .replaceAll("`", "'")
        ._replaceBoth("ya", "я")
        ._replaceBoth("yo", "ё")
        ._replaceBoth("yu", "ю")
        ._replaceBoth("g'", "ғ")
        ._replaceBoth("o'", "ў")
        ._replaceBoth("ch", "ч")
        ._replaceBoth("sh", "ш")
        ._replaceBoth("a", "а")
        ._replaceBoth("b", "б")
        ._replaceBoth("d", "д")
        ._replaceBoth("e", "е")
        ._replaceBoth("f", "ф")
        ._replaceBoth("g", "г")
        ._replaceBoth("h", "ҳ")
        ._replaceBoth("i", "и")
        ._replaceBoth("j", "ж")
        ._replaceBoth("k", "к")
        ._replaceBoth("l", "л")
        ._replaceBoth("m", "м")
        ._replaceBoth("n", "н")
        ._replaceBoth("o", "о")
        ._replaceBoth("p", "п")
        ._replaceBoth("q", "қ")
        ._replaceBoth("r", "р")
        ._replaceBoth("s", "с")
        ._replaceBoth("t", "т")
        ._replaceBoth("v", "в")
        ._replaceBoth("u", "у")
        ._replaceBoth("x", "х")
        ._replaceBoth("y", "й")
        ._replaceBoth("z", "з");
  }

  String toLatin() {
    return this
        .replaceAll("`", "'")
        ._replaceBoth("я", "ya")
        ._replaceBoth("ё", "yo")
        ._replaceBoth("ю", "yu")
        ._replaceBoth("ч", "ch")
        ._replaceBoth("ш", "sh")
        ._replaceBoth("ғ", "g'")
        ._replaceBoth("ў", "o'")
        ._replaceBoth("ц", "s")
        ._replaceBoth("а", "a")
        ._replaceBoth("б", "b")
        ._replaceBoth("д", "d")
        ._replaceBoth("е", "e")
        ._replaceBoth("ф", "f")
        ._replaceBoth("г", "g")
        ._replaceBoth("ҳ", "h")
        ._replaceBoth("и", "i")
        ._replaceBoth("ж", "j")
        ._replaceBoth("к", "k")
        ._replaceBoth("л", "l")
        ._replaceBoth("м", "m")
        ._replaceBoth("н", "n")
        ._replaceBoth("о", "o")
        ._replaceBoth("п", "p")
        ._replaceBoth("қ", "q")
        ._replaceBoth("р", "r")
        ._replaceBoth("с", "s")
        ._replaceBoth("т", "t")
        ._replaceBoth("в", "v")
        ._replaceBoth("у", "u")
        ._replaceBoth("х", "x")
        ._replaceBoth("й", "y")
        ._replaceBoth("з", "z");
  }

  String _replaceBoth(String from, String replace) {
    replace = replace.toLowerCase()[0] + replace.substring(1).toLowerCase();
    return this
        .replaceAll(from.toLowerCase(), replace.toLowerCase())
        .replaceAll(
          from.toUpperCase(),
          "${replace.toUpperCase()[0]}${replace.length == 1 ? "" : replace.substring(1).toLowerCase()}",
        );
  }

  int _editDistance(String s1, String s2) {
    s1 = s1._clearSpace();
    s2 = s2._clearSpace();

    List<int> costs = _getList(s2.length + 1);
    for (int i = 0; i <= s1.length; i++) {
      int lastValue = i;
      for (int j = 0; j <= s2.length; j++) {
        if (i == 0)
          costs[j] = j;
        else {
          if (j > 0) {
            int newValue = costs[j - 1];
            if (s1[i - 1] != s2[j - 1])
              newValue = min(min(newValue, lastValue), costs[j]) + 1;
            costs[j - 1] = lastValue;
            lastValue = newValue;
          }
        }
      }
      if (i > 0) costs[s2.length] = lastValue;
    }
    return costs[s2.length];
  }

  List<int> _getList(int length) {
    final List<int> list = [];
    for (int i = 0; i < length; i++) list.add(0);
    return list;
  }

  String _clearSpace() {
    final String s = this.trim();
    String t = "";
    bool x = true;
    for (int i = 0; i < s.length; i++) {
      if (s[i] != ' ') x = true;
      if (x) t += s[i];
      if (s[i] == ' ') x = false;
    }
    return t;
  }
}
