<?php

class LocaleText
{
  var $Data;
  var $Code;
  var $Title;

  function __construct()
  {
    $this->Data = array();
    $this->Code = 'en';
    $this->Title = 'English';
  }

  function Load()
  {
  }

  function Translate($Text, $Group = '')
  {
    if(array_key_exists($Text, $this->Data[$Group]) and ($this->Data[$Group][$Text] != ''))
      return($this->Data[$Group][$Text]);
      else return($Text);
  }

  function TranslateReverse($Text, $Group = '')
  {
    $Key = array_search($Text, $this->Data[$Group]);
    if(($Key === FALSE) or ($this->Data[$Group][$Key] == '')) return($Text);
      else return($Key);
  }
}

class LocaleFile extends Model
{
  var $Texts;
  var $Dir;

  function __construct(System $System)
  {
    parent::__construct($System);
    $this->Texts = new LocaleText();
  }

  function Load($Language)
  {
    $FileName = $this->Dir.'/'.$Language.'.php';
    if(file_exists($FileName)) {
      include_once($FileName);
      $ClassName = 'LocaleText'.$Language;
      $this->Texts = new $ClassName();
    } else throw new Exception(sprintf(T('Language file %s not found'), $FileName));
    $this->Texts->Load();
  }

  function AnalyzeCode($Path)
  {
    // Search for php files
    $FileList = scandir($Path);
    foreach($FileList as $FileName)
    {
      $FullName = $Path.'/'.$FileName;
      if(($FileName == '.') or ($FileName == '..')) ; // Skip virtual items
      else if(substr($FileName, 0, 1) == '.') ; // Skip Linux hidden files
      else if(is_dir($FullName)) $this->AnalyzeCode($FullName);
      else if(file_exists($FullName))
      {
        if(substr($FullName, -4) == '.php')
        {
          $Content = file_get_contents($FullName);
          // Search occurence of T() function
          while(strpos($Content, 'T(') !== false)
          {
            $Previous = strtolower(substr($Content, strpos($Content, 'T(') - 1, 1));
            $Content = substr($Content, strpos($Content, 'T(') + 2);
            $Ord = ord($Previous);
            //echo($Ord.',');
            if(!(($Ord >= ord('a')) and ($Ord <= ord('z'))))
            {
              // Do for non-alpha previous character
              $Original = substr($Content, 0, strpos($Content, ')'));
              $Original2 = '';
              if((substr($Original, 0, 1) == "'") and (substr($Original, -1, 1) == "'"))
                $Original2 = substr($Original, 1, -1);
              if((substr($Original, 0, 1) == '"') and (substr($Original, -1, 1) == '"'))
                $Original2 = substr($Original, 1, -1);
              if($Original2 != '')
              {
                if(!array_key_exists($Original2, $this->Texts->Data))
                  $this->Texts->Data[$Original2] = '';
              }
            }
          }
        }
      }
    }
  }

  function SaveToFile($FileName)
  {
    $Content = '<?php'."\n".
    ''."\n".
    'class LocaleText'.$this->Texts->Code.' extends LocaleText'."\n".
    '{'."\n".
    '  function Load()'."\n".
    '  {'."\n".
    '    $this->Code = \''.$this->Texts->Code.'\';'."\n".
    '    $this->Title = \''.$this->Texts->Title.'\';'."\n".
    '    $this->Data = array('."\n";
    foreach($this->Texts->Data as $Index => $Item)
    {
      $Content .= "      '".$Index."' => '".$Item."',\n";
    }
    $Content .= '    );'."\n".
    '  }'."\n".
    '}'."\n";
    file_put_contents($FileName, $Content);
  }

  function LoadFromDatabase($Database, $LangCode)
  {
    $DbResult = $Database->select('Language', '*', 'Code='.$Database->quote($LangCode));
    if($DbResult->num_rows > 0)
    {
      $Language = $DbResult->fetch_assoc();
      $this->Texts->Data = array();
      $DbResult = $Database->select('Locale', '`Original`, `Translated`', '`Language`='.$Language['Id']);
      while($DbRow = $DbResult->fetch_assoc())
        $this->Texts->Data[$DbRow['Original']] = $DbRow['Translated'];
    }
  }

  function SaveToDatabase(Database $Database, $LangCode)
  {
    $DbResult = $Database->select('Language', '*', 'Code='.$Database->quote($LangCode));
    if($DbResult->num_rows > 0)
    {
      $Language = $DbResult->fetch_assoc();
      $Database->delete('Locale', '`Language`='.$Language['Id']);
      foreach($this->Texts->Data as $Index => $Item)
        $Database->query('INSERT INTO `Locale` (`Language`,`Original`,`Translated`) '.
        'VALUES('.$Language['Id'].','.$Database->quote($Index).','.$Database->quote($Item).')');
    }
  }

  function UpdateToDatabase(Database $Database, $LangCode)
  {
    $DbResult = $Database->select('Language', '*', '`Code`='.$Database->quote($LangCode));
    if($DbResult->num_rows > 0)
    {
      $Language = $DbResult->fetch_assoc();
      foreach($this->Texts->Data as $Index => $Item)
      {
        $DbResult = $Database->select('Locale', '*', '(`Original` ='.$Database->quote($Index).
          ') AND (`Language`='.($Language['Id']).')');
        if($DbResult->num_rows > 0)
        $Database->update('Locale', '(`Language`='.($Language['Id']).') AND '.
          '(`Original` ='.$Database->quote($Index).')', array('Translated' => $Item));
        else $Database->insert('Locale', array('Language' => $Language['Id'],
         'Original' => $Index, 'Translated' => $Item));
      }
    }
  }
}

class LocaleManager extends Model
{
  var $CurrentLocale;
  var $Codes;
  var $Dir;
  var $LangCode;
  var $DefaultLangCode;
  var $Available;

  function __construct(System $System)
  {
    parent::__construct($System);
    $this->Codes = array('en');
    $this->CurrentLocale = new LocaleFile($System);
    $this->LangCode = 'en';
    $this->DefaultLangCode = 'en';
    $this->Available = array();
  }

  function LoadAvailable()
  {
    $this->Available = array();
    $FileList = scandir($this->Dir);
    foreach($FileList as $FileName)
    {
      if(substr($FileName, -4) == '.php')
      {
        $Code = substr($FileName, 0, -4);
        $Locale = new LocaleFile($this->System);
        $Locale->Dir = $this->Dir;
        $Locale->Load($Code);
        $this->Available['Code'] = array('Code' => $Code, 'Title' => $Locale->Texts->Title);
      }
    }
  }

  function UpdateAll($Directory)
  {
    $Locale = new LocaleFile($this->System);
    $Locale->AnalyzeCode($Directory);
    $FileList = scandir($this->Dir);
    foreach($FileList as $FileName)
    {
      if(substr($FileName, -4) == '.php')
      {
        $FileLocale = new LocaleFile($this->System);
        $FileLocale->Dir = $this->Dir;
        $FileLocale->Load(substr($FileName, 0, -4));

        // Add new
        foreach($Locale->Texts->Data as $Index => $Item)
          if(!array_key_exists($Index, $FileLocale->Texts->Data))
            $FileLocale->Texts->Data[$Index] = $Item;
        // Remove old
        foreach($FileLocale->Texts->Data as $Index => $Item)
          if(!array_key_exists($Index, $Locale->Texts->Data))
            unset($FileLocale->Texts->Data[$Index]);
        $FileLocale->UpdateToDatabase($this->System->Database, $FileLocale->Texts->Code);
        $FileName = $this->Dir.'/'.$FileLocale->Texts->Code.'.php';
        $FileLocale->SaveToFile($FileName);
      }
    }
    $this->CurrentLocale->Load($this->CurrentLocale->Texts->Code);
  }

  function LoadLocale($Code)
  {
    if(array_key_exists($Code, $this->Available))
    {
      $this->CurrentLocale->Dir = $this->Dir;
      $this->CurrentLocale->Load($Code);
    } else throw new Exception(sprintf(T('Unsupported locale code %s'), $Code));
  }
}

// Short named global translation function
function T($Text, $Group = '')
{
  global $GlobalLocaleManager;

  if(isset($GlobalLocaleManager)) return($GlobalLocaleManager->CurrentLocale->Texts->Translate($Text, $Group));
    else return($Text);
}
