<?php

class LanguageInfo
{
  /** @var string */
  public $language;
  /** @var LanguageInfo */
  public $parent = null;

  /**
   *
   * @param string $lang
   */
  public function __construct($lang)
  {
    $this->language = $lang;
    $parentLangsIndex = strrpos($this->language, "_");
    if($parentLangsIndex !== false)
    {
      $parentLangs = substr($this->language, 0, $parentLangsIndex);
      $this->parent = new LanguageInfo($parentLangs);
    }
  }

  /**
   *
   * @param string $type
   * @param string $category
   * @param string $message
   * @return boolean
   */
  public function addMessageType($type,$category,$message,$body=null)
  {
    $messages = $this->loadMessageType($type, $category);
    $messages[$message] = onNull($body, $message);
    return $this->saveMessageType($type, $category, $messages);
  }

  /**
   *
   * @param string $type
   * @param string $category
   * @param string $message
   * @return boolean
   */
  public function removeMessageType($type,$category,$message)
  {
    $messages = $this->loadMessageType($type, $category);
    //if(array_key_exists($message, $messages))
    unset($messages[$message]);
    return $this->saveMessageType($type, $category, $messages);
  }

  /**
   *
   * @param string $type
   * @param string $category
   * @param string[] $messages
   * @return boolean
   */
  public function saveMessageType($type,$category,array $messages)
  {
    $pathLang = pathCombine(app()->basePath, "messages", $this->language);
    if(!isEmpty($type))
      $pathLang = pathCombine($pathLang, $type);
    if(!dirExists($pathLang))
    if(mkdir($pathLang,null,true) === false)
      return false;
    $filename = pathCombine($pathLang, "$category.php");
    $data = "<?php return ".array_from_array_to_code($messages).";";
    $lockName = strtoupper(md5(strtoupper($filename)));
    $result = false;
    $cs = new CriticalSection($lockName);
    if($cs->lock())
    {
      $result = file_put_contents($filename, $data) !== false;
      $cs->unlock();
    }
    else
    {
      $result = file_put_contents($filename, $data) !== false;
    }
    return $result;
  }

  /**
   *
   * @param string $type
   * @param string $category
   * @return string[]
   */
  public function loadMessageType($type,$category)
  {
    $pathLang = pathCombine(app()->basePath, "messages", $this->language);
    if(!isEmpty($type))
      $pathLang = pathCombine($pathLang, $type);
    if(!dirExists($pathLang))
      mkdir($pathLang,null,true);
    $filename = pathCombine($pathLang, "$category.php");
    if(fileExists($filename))
    {
      $ignored = include($filename);
      if(is_array_ex($ignored, true))
        return $ignored;
    }
    return array();
  }

  /**
   *
   * @param string $type
   * @param string $category
   * @param string $message
   * @return boolean
   */
  public function isMessageType($type,$category,$message)
  {
    $messages = $this->loadMessageType($type, $category);
    return array_key_exists($message, $messages);
  }

  /**
   *
   * @param string $type
   * @param string $category
   * @param string $message
   * @return string
   */
  public function getMessageType($type,$category,$message)
  {
    $messages = $this->loadMessageType($type, $category);
    if(array_key_exists($message, $messages))
      return $messages[$message];
    return null;
  }

  /**
   *
   * @return LanguageInfo[]
   */
  public static function getLanguages()
  {
    $messagesFolderPath = pathCombine(app()->basePath, "messages");
    $messagesFolder = new DirectoryIterator($messagesFolderPath);
    $langs = array();
    foreach($messagesFolder as $langFolder)
    {
      if(!$langFolder->isDot() && $langFolder->isDir())
      {
        $lang = $langFolder->getFilename();
        $langs[$lang] = new LanguageInfo($lang);
      }
    }
    return $langs;
  }

  public function t($category, $message, array $params=array())
  {
    return Yii::t($category,$message,$params,null,$this->language);
  }

  public static function getAllSources()
  {
    $sources = array();
    foreach(self::getLanguages() as $l)
      $sources = $sources + $l->getSources();
    array_remove_dup($sources);
    return $sources;
  }

  public function getTranslatedMessages($category)
  {
    return $this->loadMessageType(null, $category);
  }

  public function isUntranslated($category, $message)
  {
    return $this->isMessageType('untranslated', $category, $message);
  }

  public function getSourcesByCategory($category)
  {
    return array_keys($this->loadMessageType(null, $category));
  }

  public function getSources()
  {
    $sources = array();
    foreach($this->getCategories() as $category)
      $sources = $sources + $this->getSourcesByCategory($category);
    array_remove_dup($sources);
    sort($sources);
    return $sources;
  }

  /**
   *
   * @return string[]
   */
  public function getCategories()
  {
    $pathLang = pathCombine(app()->basePath, "messages", $this->language);
    $dirLang = new DirectoryIterator($pathLang);
    $categories = array();
    foreach($dirLang as $catFile)
    if($catFile->isFile())
    {
      $cat = endsWithGet($catFile->getFilename(), ".php");
      if(!isEmpty($cat))
        array_add_unique($categories, $cat);
    }
    if($this->parent != null)
    foreach($this->parent->getCategories() as $cat)
      array_add_unique($categories, $cat);
    return $categories;
  }

  public function __toString()
  {
    return $this->language;
  }
}