<?php

namespace Drupal\straker_translate;

use Drupal\Component\Serialization\Json;

/**
 * A utility class for Straker translation.
 */
class StrakerTranslateLocale {

  /**
   * A map of Drupal language codes to Straker Translate language codes.
   */
  protected static $language_map = [
  // Afrikaans.
    'af'        => '917FED4D-096F-BBAD-004F-5025AD441B4E',
  // Amharic.
    'am'        => '917TYE16-BD1C-1011-30C7-C5A9339BBE88',
  // Arabic.
    'ar'        => '917FEE16-BD1C-1011-30C7-C5A9339BBE99',
  // Asturian.
    'ast'       => NULL,
  // Azerbaijani.
    'az'        => NULL,
  // Belarusian.
    'be'        => '917FEEC1-B970-135B-1F6A-E808371C061B',
  // Bulgarian.
    'bg'        => '917FF02E-AD9B-B95C-E45C-721ED081B1F7',
  // Bengali.
    'bn'        => NULL,
  // Tibetan.
    'bo'        => NULL,
  // Breton.
    'br'        => NULL,
  // Bosnian.
    'bs'        => '917FEF76-FBB2-1FF3-F5A8-049EF63F52CB',
  // Catalan.
    'ca'        => '917FF0E0-A2E0-2E8E-BE41-D7A79411B346',
  // Czech.
    'cs'        => '917FF2A2-B873-2E61-BC4B-3E818C258B4A',
  // Welsh.
    'cy'        => '91800D55-0993-DA33-9E4B-DAF9F96CB1E3',
  // Danish.
    'da'        => '917FF2FB-DC12-0496-7022-35CA015FBBF8',
  // German.
    'de'        => '917FF7D8-9107-0BF8-97EE-065C20F453DE',
  // Dzongkha.
    'dz'        => NULL,
  // Greek.
    'el'        => '917FF883-D048-4B45-4472-7C3B412C0976',
  // English (US)
    'en'        => '917FF4B9-0808-A1F1-BCBF-A24974373286',
  // English (UK)
    'en-gb'     => '917FF462-E945-9CFC-AF66-0E33A049994C',
  // Simple English.
    'en-x-simple' => NULL,
  // Esperanto.
    'eo'        => '917FF511-91CF-A728-E431-DAD7C5113009',
  // Spanish (Spain)
    'es'        => '9180091F-A19B-AB12-E1C5-925AC5287A64',
  // Estonian.
    'et'        => '917FF569-A41E-958E-1978-BA02551FC494',
  // Basque.
    'eu'        => 'B36887D6-D7DF-4586-862B-9C04CF3EA5AD',
  // Persian.
    'fa'        => '91800888-CEB6-62D0-5DAB-888D107B0BFA',
  // Finnish.
    'fi'        => '917FF67D-9B44-A7A5-3273-47B8E6AF0C88',
  // Filipino.
    'fil'       => NULL,
  // Faeroese.
    'fo'        => NULL,
  // French (France)
    'fr'        => '917FF728-0725-A033-1278-33025F49CA40',
  // Frisian, Western.
    'fy'        => NULL,
  // Irish Gaelic.
    'ga'        => '917FFB36-0C1F-DBFC-5FA6-6FB3AE56335F',
  // Scots Gaelic.
    'gd'        => NULL,
  // Galician.
    'gl'        => NULL,
  // Swiss German.
    'gsw-berne' => NULL,
  // Gujarati.
    'gu'        => '82DAED9E-237F-4C93-BB88-BE98781DCFDA',
  // Hawaiian.
    'haw'       => NULL,
  // Hebrew.
    'he'        => '917FF987-E57C-9450-C0B0-3D23F84A2BA9',
  // Hindi.
    'hi'        => '917FF9E2-0981-B091-A8F9-F5B8A855760C',
  // Croatian.
    'hr'        => '917FF246-E282-3B67-5AF9-15E92B4087FB',
  // Haitian Creole.
    'ht'        => '917FF8D7-FD6F-0B4F-1E97-80A7AC626950',
  // Hungarian.
    'hu'        => '917FFA3A-CBB2-5ED9-98B6-8B6FFDD98374',
  // Armenian.
    'hy'        => '917FEE6B-0C4E-CA87-896B-28B8385BA0A3',
  // Indonesian.
    'id'        => '917FFAE4-AA5E-F557-020B-5AB8DBE9FD64',
  // Icelandic.
    'is'        => '917FFA8F-F9F8-2E3D-3FB9-22BBDA20E497',
  // Italian.
    'it'        => '917FFB89-CB22-CC9B-F30B-D67DB02919EE',
  // Japanese.
    'ja'        => '917FFC38-03CD-48F0-41B7-98339C754247',
  // Javanese.
    'jv'        => '917FFC8E-DADA-61F6-7F4C-95BA51034D53',
  // Georgian.
    'ka'        => '917FF782-A08E-9EC6-F832-44578D07F1B0',
  // Kazakh.
    'kk'        => '917FFCE6-9CC3-2250-69F3-4EB0065F8D19',
  // Khmer.
    'km'        => '917FFD40-01E9-299B-C466-B850B7322B69',
  // Kannada.
    'kn'        => NULL,
  // Korean.
    'ko'        => '917FFE50-E9D8-247D-59A2-789E830D27C6',
  // Kurdish.
    'ku'        => NULL,
  // Kyrgyz.
    'ky'        => '7D4E4554-357F-4C3E-8BB2B38B5A5F98E5',
  // Lao.
    'lo'        => '887FFF51-96FA-2D5E-4C85-61F9E74E1D39',
  // Lithuanian.
    'lt'        => '91800005-D37C-B24D-BC56-7C7172F52A48',
  // Latvian.
    'lv'        => '917FFFAB-9D27-14A1-6D85-B65D777FE026',
  // Malagasy.
    'mg'        => 'D4CCFCFB-D5EE-4249-944F-D80981AC9CA4',
  // Macedonian.
    'mk'        => '9180005D-CF84-7E00-937D-8B60880A8A9C',
  // Malayalam.
    'ml'        => '36244308-9EC6-4BA1-A88B-9A9FD5765BC9',
  // Mongolian.
    'mn'        => '918001AA-B4C4-C139-EDCA-BD842678EAFA',
  // Marathi.
    'mr'        => '818000B8-B804-B457-4477-7E50DB701A79',
  // Malay.
    'ms'        => '918000B8-A804-B457-4481-7E50DB701A79',
  // Maltese.
    'mt'        => '9180010A-FE09-2485-48A7-B96052DBE8E9',
  // Burmese.
    'my'        => NULL,
  // Norwegian Bokmål.
    'nb'        => '918002C2-B890-ADD6-0CB9-A82C3AA27996',
  // Nepali.
    'ne'        => '91800200-F614-316A-957D-AC4266D801C6',
  // Dutch.
    'nl'        => '917FF358-FF2B-5CAB-3738-E119AC17B9CF',
  // Norwegian Nynorsk.
    'nn'        => '5A5636C6-9676-439E-8E72D6FF5C2B5988',
  // Occitan.
    'oc'        => NULL,
  // Odia.
    'or'        => NULL,
  // Ossetian.
    'os'        => NULL,
  // Punjabi.
    'pa'        => '918004B9-CBB2-DBF5-7B4C-5B84A670E2F4',
  // Polish.
    'pl'        => '91800395-CEB6-62D0-5DAB-296D107B0BFA',
  // Persian, Afghanistan.
    'prs'       => '91800888-CEB6-62D0-5DAB-888D107B0BFA',
  // Pashto.
    'ps'        => NULL,
  // Portuguese (general)
    'pt'        => '91800468-E9B0-6799-1877-85798B4E53AC',
  // Portuguese (Brazil)
    'pt-br'     => '918003EF-F833-7099-E05C-E453DD3C3F56',
  // Portuguese (Portugal)
    'pt-pt'     => '91800468-E9B0-6799-1877-85798B4E53AC',
  // Rohingya.
    'rhg'       => NULL,
  // Rumantsch Grischun.
    'rm-rumgr'  => NULL,
  // Romanian.
    'ro'        => '9180055F-ABE5-DF04-3E50-B27BA455150F',
  // Russian.
    'ru'        => '918005AD-CDFB-80AF-4068-52098A5D78DB',
  // Kinyarwanda.
    'rw'        => NULL,
  // Scots.
    'sco'       => NULL,
  // Northern Sami.
    'se'        => NULL,
  // Sinhala.
    'si'        => '918006D5-9718-F187-CC63-E894DAE949F1',
  // Slovak.
    'sk'        => '91800737-95DE-CC1B-2109-79C2A355072F',
  // Slovenian.
    'sl'        => '9180078B-A95C-4797-C171-642C7F7AC611',
  // Albanian.
    'sq'        => '917FEDBE-AFE8-EDE1-8C37-309B9964C3A7',
  // Serbian.
    'sr'        => '9180064C-E9CE-2292-A9F9-CCD8D547595A',
  // Swedish.
    'sv'        => '918009C2-B6D4-F8D0-3FB8-08A53CDC8802',
  // Swahili.
    'sw'        => '91800972-B6F6-0EE7-65FD-1E44E4808294',
  // Tamil.
    'ta'        => '91800ABA-A897-BF5F-43B4-FBA3A2C674BF',
  // Tamil, Sri Lanka.
    'ta-lk'     => NULL,
  // Telugu.
    'te'        => NULL,
  // Thai.
    'th'        => '91800B08-B364-8232-0E3E-E9E2E9187671',
  // Turkish.
    'tr'        => '91800BFF-D9A7-EF41-F254-00B02849D291',
  // Tuvan.
    'tyv'       => NULL,
  // Uyghur.
    'ug'        => NULL,
  // Ukrainian.
    'uk'        => '91800C52-A425-EFDF-A300-216F145F5E9E',
  // Urdu.
    'ur'        => '91800CA6-B9B3-E794-32B7-44F42C2878CD',
  // Vietnamese.
    'vi'        => '91800CFD-E611-FF7F-69B7-0F76D0E3749C',
  // Lolspeak.
    'xx-lolspeak' => NULL,
  // Chinese Simplified.
    'zh-hans'  => '917FF13D-AAC6-611A-2C7F-B964ED472450',
  // Chinese Traditional.
    'zh-hant'  => '917FF198-0ADB-AC7A-569D-8CA0678B772C',
  ];

  /**
   * Converts the Straker Translate language code for the specified Drupal language code.
   *
   * @param string $drupal_language_code
   *   A Drupal language code.
   *
   * @return mixed
   *   The Straker Translate language code if there is a match for the passed language code,
   *   FALSE otherwise.
   */
  public static function convertDrupal2StrakerTranslate(string $drupal_language_code): ?string {
    $filtered_map = array_filter(self::$language_map, function ($value) {
      return $value !== NULL;
    });
    $return = $filtered_map[$drupal_language_code] ?? NULL;
    return $return;
  }

  /**
   * Gets the Drupal language code for the specified Straker Translate language code.
   *
   * @param string $straker_translate_locale
   *   A Straker Translate language code. (e.g., 'de_DE', 'pt_BR', 'fr_FR')
   *
   * @return mixed
   *   The Drupal language code if there is a match for the passed language code, (e.g., 'de-de', 'pt-br',' fr-fr')
   *   FALSE otherwise.
   */
  public static function convertStrakerTranslate2Drupal(string $straker_translate_locale): ?string {
    $filtered_map = array_filter(self::$language_map, function ($value) {
      return $value !== NULL;
    });
    $reverse_map = array_flip($filtered_map);
    return $reverse_map[$straker_translate_locale] ?? NULL;
  }

  /**
   *
   */
  public static function generateStrakerTranslate2Drupal($straker_translate_locale) {
    // Standard conversion.
    $drupal_language_code = strtolower(str_replace("_", "-", $straker_translate_locale));
    if ($hyphen_index = strpos($drupal_language_code, '-') > 0) {
      $drupal_general_code = substr($drupal_language_code, 0, strpos($drupal_language_code, '-'));
    }
    else {
      // We try with the given language, if we didn't have an hyphen (e.g. ar).
      $drupal_general_code = $drupal_language_code;
    }

    // Check enabled list.
    $enabled_languages = \Drupal::languageManager()->getLanguages();
    $enabled_codes = array_keys($enabled_languages);

    if (!in_array($drupal_general_code, $enabled_codes)) {
      return $drupal_general_code;
    }
    elseif (!in_array($drupal_language_code, $enabled_codes)) {
      return $drupal_language_code;
    }
    else {
      return $drupal_language_code . rand(10, 99);
    }
  }

  /**
   *
   */
  public static function testConvertFunctions() {
    $result = [
      "drupal => straker_translate" => [],
      "straker_translate => drupal" => [],
    ];
    // Drupal => straker_translate.
    foreach (self::$language_map as $drupal_language_code => $straker_translate_locale) {
      $ret_straker_translate_locale = self::convertDrupal2StrakerTranslate($drupal_language_code);
      if (strcmp($straker_translate_locale, $ret_straker_translate_locale) !== 0) {
        $result["drupal => straker_translate"][] = "[$drupal_language_code => $ret_straker_translate_locale] !== $straker_translate_locale";
      }
    }
    // Straker Translate => drupal.
    foreach (self::$language_map as $drupal_language_code => $straker_translate_locale) {
      $ret_drupal_language_code = self::convertStrakerTranslate2Drupal($straker_translate_locale);
      if (strcmp($drupal_language_code, $ret_drupal_language_code) !== 0) {
        $result["straker_translate => drupal"][] = "[$straker_translate_locale => $ret_drupal_language_code] !== $drupal_language_code";
      }
    }

    return $result;
  }

  /**
   * Returns whether the given language is supported.
   *
   * @return bool
   *   Boolean value.
   */
  public static function isSupportedLanguage($drupal_language_code) {
    // ($drupal_language_code != LANGUAGE_NONE)
    $supported = (self::convertDrupal2StrakerTranslate($drupal_language_code) !== FALSE);
    if (!$supported) {
      \Drupal::logger('straker_translate')->warning("Unsupported language detected: [@language]", ['@language' => $drupal_language_code]);
    }
    return $supported;
  }

  /**
   * Gets the site's available target languages for Straker translation.
   *
   * @param mixed $pluck_field
   *   NULL - return the entire object
   *   string - return an array of just the pluck_field specified (if it exists)
   *   array - return an array of the selected fields.
   *
   * @return array
   *   An array of Straker Translate language codes.
   */
  public static function getLanguages($pluck_field = NULL, $include_disabled = FALSE, $straker_translate_locale_to_exclude = NULL) {
    // straker_translate_add_missing_locales(FALSE);
    $languages = [];

    foreach (\Drupal::languageManager()->getLanguages() as $target_language) {
      $locale = $target_language->straker_translate_locale ?? NULL;
      $enabled = $target_language->straker_translate_enabled ?? NULL;
      if (!$locale || $locale == $straker_translate_locale_to_exclude) {
        continue;
      }
      $language = (is_string($pluck_field) && isset($target_language->$pluck_field)) ? $target_language->$pluck_field : $target_language;
      // Include all languages enabled.
      if ($enabled) {
        $languages[$enabled] = $language;
        // Include all languages, including disabled (straker_translate_enabled is 0)
      }
      elseif ($include_disabled) {
        $languages[$locale] = $language;
      }
    }
    return $languages;
  }

  /**
   *
   */
  public static function getLanguagesWithoutSource($source_straker_translate_locale) {
    return self::getLanguages('straker_translate_locale', FALSE, $source_straker_translate_locale);
  }

  /**
   *
   */
  public static function getLanguagesWithoutSourceAsJSON($source_straker_translate_locale) {
    return Json::encode(array_values(self::getLanguages('straker_translate_locale', FALSE, $source_straker_translate_locale)));
  }

}
