<?php

namespace App\Core\Helper;
use Exception;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;

class LanguageService
{
    private static $currentLanguage = null;
    private static $languageSupportList = null;
    private static $languageSupportCacheName = "langSupportCache";

    public static function getDefaultLang()
    {
        return config("languageSupport.defaultLanguage");
    }

    public static function getCurrentLang (  )
    {
        $language = self::$currentLanguage;
        $language = $language ? $language : self::getDefaultLang();
        return $language;
    }

    public static function isValidLanguage ( $language )
    {
        $validLanguages = self::getValidLanguages();
        return in_array($language,$validLanguages);
    }

    public static function  getCurrentLangPack($language = null)
    {
        $language = $language ? $language : self::getCurrentLang();
        return config("language-pack-".$language);
    }


    public static function setCurrentLanguage($language)
    {
        $language = strtolower($language);
        self::$currentLanguage = self::isValidLanguage($language) ? $language : config("languageSupport.defaultLanguage");
        return self::$currentLanguage;
    }

    public static function getValidLanguages ( $except = null )
    {
        return collect(config("languageSupport.availableLanguages"))->flip()->except($except)->flip()->toArray();
    }

    public static function getAllLangPackages()
    {
        $langPackages = [];
        $validSystemLanguages = self::getValidLanguages();
        foreach ($validSystemLanguages as $perLanguage)
        {
            $langPackages[$perLanguage] = self::getCurrentLangPack($perLanguage);
        }
        return $langPackages;
    }

    public static function convertAllLanguageSettingsAndCache()
    {
        $cacheParam = [];
        $wordIndexCounter = 0;
        $allLangPackages = self::getAllLangPackages();
        $systemDefaultLang = self::getDefaultLang();

        foreach ($allLangPackages[$systemDefaultLang] as $perLangKey => $perLangWord)
        {
            $cacheParam[$wordIndexCounter]["md5"] = self::convertToMd5ForMultiLanguage($perLangWord);

            foreach ($allLangPackages as $perLangPackKey => $perLangPack)
            {
                $cacheParam[$wordIndexCounter][$perLangPackKey] = $perLangPack[$wordIndexCounter];
            }
            $wordIndexCounter++;
        }

        $cacheParam = collect($cacheParam)->keyBy("md5")->toArray();
        Cache::put(self::$languageSupportCacheName,$cacheParam,120);
        return $cacheParam;
    }

    public static function  getLanguageSupportList()
    {
        $cachedData = self::$languageSupportList;
        if ( !$cachedData)
        {
            $cachedData = Cache::get(self::$languageSupportCacheName);
            self::$languageSupportList = $cachedData;
        }
        $cachedData = $cachedData ? $cachedData : self::convertAllLanguageSettingsAndCache();
        return $cachedData;
    }


    private static function makeSlugForMultiLanguage( $word )
    {
        $word = lowerCase($word);
        preg_match_all("#[\pL\d+]+#iu",$word,$results);
        $results = $results[0];
        $converted = implode("",$results);
        return $converted;
    }

    public static function convertToMd5ForMultiLanguage($word)
    {
        /*Clear The Parameters*/
        $word = preg_replace('/\{\#\d+\}/',"",$word);
        /**/
        /*Clear From Html*/
        $word = strip_tags($word);
        /**/
        $word = self::makeSlugForMultiLanguage($word);
        return md5($word);
    }


    public static function findWordForLanguage($word,$lang,array $parameters = [])
    {
        $md5Key = self::convertToMd5ForMultiLanguage($word);
        $langSupportList = self::getLanguageSupportList();
        $converted =  fillOnUndefined($langSupportList,$md5Key.".".$lang);
        $converted = $converted ? $converted : fillOnUndefined($langSupportList,$md5Key.".".self::getDefaultLang());
        $converted = $converted ? $converted : $word;

        /*Inject Parameters*/
        $parameters = reIndexArrayKeys($parameters,1);
        foreach ($parameters as $perParameterKey => $perParameter)
        {
            $converted = preg_replace('/\{\#'.$perParameterKey.'\}/',$perParameter,$converted);
        }
        /**/

        return $converted;
    }

    public static function lang ( $word,array $parameters = [],$lang = null )
    {
        $lang = $lang ? : self::$currentLanguage;
        return self::findWordForLanguage($word,$lang,$parameters);
    }

    public static function langArrayStack ( array $langParamStack )
    {
        $result = [];
        $validCases = ["lower","title","upper"];

        foreach ($langParamStack as $perLangParam)
        {
            $word = castToString(fillOnUndefined($perLangParam,"word"));
            $parameters = fillOnUndefined($perLangParam,"parameters",[]);
            $lang = castToString(fillOnUndefined($perLangParam,"lang"));
            $case = lowerCase(castToString(fillOnUndefined($perLangParam,"case")));
            $case = in_array($case,$validCases) ? $case : null;
            $caseFunction = $case ? camel_case("lang".$case."case") : "lang";
            $result[] = self::$caseFunction($word,$parameters,$lang);
        }

        return $result;
    }

    public static function langArray ( array $words, $lang = null )
    {
        $result = [];
        foreach ($words as $perWord)
        {
            $result[] = self::lang($perWord, [], $lang);
        }
        return $result;
    }

    public static function langLowerCase($word,array $parameters = [],$lang = null)
    {
        $lang = $lang ? : self::getCurrentLang();
        $translated = self::lang($word, $parameters,$lang);
        return $lang == "tr" ? lowerCase($translated) : mb_strtolower($translated);
    }

    public static function langTitleCase($word,array $parameters = [],$lang = null)
    {
        $lang = $lang ? : self::getCurrentLang();
        $translated = self::lang($word, $parameters,$lang);
        return $lang == "tr" ? uCase($translated) : mb_convert_case($translated,MB_CASE_TITLE);
    }

    public static function langUpperCase($word,array $parameters = [],$lang = null)
    {
        $lang = $lang ? : self::getCurrentLang();
        $translated = self::lang($word, $parameters,$lang);
        return $lang == "tr" ? upperCase($translated) : mb_strtoupper($translated);
    }


}
