<?php

use ProcessMaker\Core\System;

class Language extends BaseLanguage
{
    private static $arrayRecord = array();

    private $exceptionFields = array ('','javascript','hidden','phpvariable','private','toolbar','xmlmenu','toolbutton','cellmark','grid','CheckboxTable');

    public function load ($sLanUid)
    {
        try {
            $oRow = LanguagePeer::retrieveByPK( $sLanUid );
            if (! is_null( $oRow )) {
                $aFields = $oRow->toArray( BasePeer::TYPE_FIELDNAME );
                $this->fromArray( $aFields, BasePeer::TYPE_FIELDNAME );
                $this->setNew( false );
                return $aFields;
            } else {
                throw (new Exception( 'This row doesn\'t exist!' ));
            }
        } catch (Exception $oError) {
            throw ($oError);
        }
    }

    public function update ($aFields)
    {
        $oConnection = Propel::getConnection( LanguagePeer::DATABASE_NAME );
        try {
            $oConnection->begin();
            $this->load( $aFields['LAN_ID'] );
            $this->fromArray( $aFields, BasePeer::TYPE_FIELDNAME );
            if ($this->validate()) {
                $iResult = $this->save();
                $oConnection->commit();
                return $iResult;
            } else {
                $oConnection->rollback();
                throw (new Exception( 'Failed Validation in class ' . get_class( $this ) . '.' ));
            }
        } catch (Exception $e) {
            $oConnection->rollback();
            throw ($e);
        }
    }

    //SELECT LAN_ID, LAN_NAME FROM LANGUAGE WHERE LAN_ENABLED = '1' ORDER BY LAN_WEIGHT DESC
    public function getActiveLanguages ()
    {
        $oCriteria = new Criteria( 'workflow' );
        $oCriteria->addSelectColumn( LanguagePeer::LAN_ID );
        $oCriteria->addSelectColumn( LanguagePeer::LAN_NAME );
        $oCriteria->add( LanguagePeer::LAN_ENABLED, '1' );
        $oCriteria->addDescendingOrderByColumn( LanguagePeer::LAN_WEIGHT );

        $oDataset = ContentPeer::doSelectRS( $oCriteria );
        $oDataset->setFetchmode( ResultSet::FETCHMODE_ASSOC );

        $oContent = new Content();
        $rows = Array ();
        while ($oDataset->next()) {
            array_push( $rows, $oDataset->getRow() );
        }

        return $rows;
    }

    public function findById ($LAN_ID)
    {
        if (strpos($LAN_ID, '_') !== false) {
            $aux = explode('_', $LAN_ID);
            $LAN_ID = $aux[0];
        }
        $oCriteria = new Criteria( 'workflow' );
        $oCriteria->addSelectColumn( LanguagePeer::LAN_ID );
        $oCriteria->addSelectColumn( LanguagePeer::LAN_NAME );
        $oCriteria->add( LanguagePeer::LAN_ID, $LAN_ID );
        $oDataset = LanguagePeer::doSelectRS( $oCriteria );
        $oDataset->setFetchmode( ResultSet::FETCHMODE_ASSOC );
        $oDataset->next();
        return $oDataset->getRow();
    }

    public function findByLanName ($LAN_NAME)
    {
        $oCriteria = new Criteria( 'workflow' );
        $oCriteria->addSelectColumn( LanguagePeer::LAN_ID );
        $oCriteria->addSelectColumn( LanguagePeer::LAN_NAME );
        $oCriteria->add( LanguagePeer::LAN_NAME, $LAN_NAME, Criteria::LIKE );
        $oDataset = LanguagePeer::doSelectRS( $oCriteria );
        $oDataset->setFetchmode( ResultSet::FETCHMODE_ASSOC );
        $oDataset->next();
        return $oDataset->getRow();
    }

    public function findLocationByLanId($languageId)
    {
        try {
            if (!isset(self::$arrayRecord[$languageId])) {
                $criteria = new Criteria("workflow");

                $criteria->addSelectColumn(LanguagePeer::LAN_LOCATION);
                $criteria->add(LanguagePeer::LAN_ID, $languageId, Criteria::LIKE);

                $rsCriteria = LanguagePeer::doSelectRS($criteria);
                $rsCriteria->setFetchmode(ResultSet::FETCHMODE_ASSOC);

                $rsCriteria->next();

                self::$arrayRecord[$languageId] = $rsCriteria->getRow();
            }

            $record = self::$arrayRecord[$languageId];

            //Return
            return $record;
        } catch (Exception $e) {
            throw $e;
        }
    }

    /**
     * Import a language file
     *
     * @param string $languageFile
     * @param bool $updateXml
     * @param bool $updateDB
     * @param bool $generateMafe
     * @return Object
     * @throws Exception
     */
    public function import($languageFile, $updateXml = true, $updateDB = true, $generateMafe = true)
    {
        try {
            $translation = new Translation();
            try {
                //We get all MichelangeloFE and PMDynaform translatable labels.
                $labels = array_merge(self::getLabelsMafe(), self::getLabelsPMDynaform());
                foreach ($labels as $label) {
                    $translation->addTranslation('LABEL', 'ID_MAFE_' . G::encryptOld($label), 'en', $label);
                }
            } catch (Exception $e) {
                error_log($e->getMessage());
            }

            $POFile = new i18n_PO($languageFile);
            $POFile->readInit();
            $POHeaders = $POFile->getHeaders();

            /*getting the PO Language definition*/
            $langName = $POHeaders['X-Poedit-Language'];
            //find the lang id
            $language = new Language();
            $langRecord = $language->findByLanName($langName);

            if (!isset($langRecord['LAN_ID'])) {
                $langRecord = $language->findById($langName);
                if (!isset($langRecord['LAN_ID'])) {
                    //if the language doesn't exist abort
                    throw new Exception('The .po file has a invalid X-Poedit-Language definition!');
                }
            }

            $languageID = $langRecord['LAN_ID'];

            /*getting the PO Language definition*/
            $countryName = $POHeaders['X-Poedit-Country'];
            if ($countryName != '.') {
                $isoCountry = new IsoCountry();
                $countryRecord = $isoCountry->findByIcName($countryName);

                if (!isset($countryRecord['IC_UID'])) {
                    //if the language doesn't exist abort
                    throw new Exception('The .po file has a invalid X-Poedit-Country definition!');
                }

                $countryID = $countryRecord['IC_UID'];
                //define locale
                $LOCALE = "$languageID-$countryID";
            } else {
                $LOCALE = $languageID;
            }

            $countItems = 0;
            $countItemsSuccess = 0;
            $errorMsg = '';

            while ($rowTranslation = $POFile->getTranslation()) {
                $countItems++;
                if (!isset($POFile->translatorComments[0]) || !isset($POFile->translatorComments[1]) || !isset($POFile->references[0])) {
                    throw new Exception('The .po file doesn\'t have valid directives for Processmaker!');
                }

                foreach ($POFile->translatorComments as $a => $aux) {
                    $aux = trim($aux);
                    if ($aux == 'TRANSLATION') {
                        $identifier = $aux;
                    } else {
                        $var = explode('/', $aux);
                        if ($var[0] == 'LABEL') {
                            $context = $aux;
                        }
                        if ($var[0] == 'JAVASCRIPT') {
                            $context = $aux;
                        }
                    }
                    if (preg_match('/^([\w-]+)\/([\w-]+\/*[\w-]*\.xml\?)/', $aux, $match)) {
                        $identifier = $aux;
                    } else {
                        if (preg_match('/^([\w-]+)\/([\w-]+\/*[\w-]*\.xml$)/', $aux, $match)) {
                            $context = $aux;
                        }
                    }
                }

                $reference = $POFile->references[0];

                // it is a Sql insert on TRANSLATIONS TAble
                if ($identifier == 'TRANSLATION') {
                    if ($updateDB) {
                        list ($category, $id) = explode('/', $context);
                        $result = $translation->addTranslation($category, $id, $LOCALE, trim(stripcslashes(str_replace(chr(10), '', $rowTranslation['msgstr']))));
                        if ($result['codError'] == 0) {
                            $countItemsSuccess++;
                        } else {
                            $errorMsg .= $id . ': ' . $result['message'] . "\n";
                        }
                    }
                }                 // is a Xml update
                elseif ($updateXml) {
                    $xmlForm = $context;
                    //erik: expresion to prevent and hable correctly dropdown values like -1, -2 etc.
                    preg_match('/^([\w_]+)\s-\s([\w_]+)\s*-*\s*([\w\W]*)$/', $reference, $match);

                    if (!file_exists(PATH_XMLFORM . $xmlForm)) {
                        $errorMsg .= 'file doesn\'t exist: ' . PATH_XMLFORM . $xmlForm . "\n";
                        continue;
                    }

                    if (count($match) < 4) {
                        $near = isset($rowTranslation['msgid']) ? $rowTranslation['msgid'] : (isset($rowTranslation['msgstr']) ? $rowTranslation['msgstr'] : '');
                        $errorMsg .= "Invalid Translation reference: \"$reference\",  near -> " . strip_tags($near) . "\n";
                        continue;
                    }


                    $dynaform = new DynaformHandler(PATH_XMLFORM . $xmlForm);
                    $fieldName = $match[2];

                    $codes = explode('-', $reference);

                    if (sizeof($codes) == 2) {
                        //is a normal node
                        $dynaform->addChilds($fieldName, Array($LOCALE => stripcslashes(str_replace(chr(10), '', $rowTranslation['msgstr']))
                        ));
                    } elseif (sizeof($codes) > 2) {
                        //is a node child for a language node
                        $name = $match[3] == "''" ? '' : $match[3];
                        $childNode = Array(Array('name' => 'option', 'value' => $rowTranslation['msgstr'], 'attributes' => Array('name' => $name
                        )
                        )
                        );

                        $dynaform->addChilds($fieldName, Array($LOCALE => null
                        ), $childNode);
                    }
                    $countItemsSuccess++;
                }
            }

            $language = new Language();
            $language->update(array('LAN_ID' => $languageID, 'LAN_ENABLED' => '1'
            ));

            if ($updateXml) {
                $trn = new Translation();
                $trn->generateFileTranslation($LOCALE);
                $trn->addTranslationEnvironment($LOCALE, $POHeaders, $countItemsSuccess);
            }

            if ($generateMafe) {
                $trn = new Translation();
                $trn->generateFileTranslationMafe();
            }

            //fill the results
            $results = new stdClass();
            $results->recordsCount = $countItems;
            $results->recordsCountSuccess = $countItemsSuccess;
            $results->lang = $languageID;
            $results->headers = $POHeaders;
            $results->errMsg = $errorMsg;

            G::auditLog("UploadLanguage", "Language: " . $languageID);

            return $results;
        } catch (Exception $error) {
            throw ($error);
        }
    }

    /**
     * Export language to Download
     * @throws Exception
     */
    public function export ()
    {
        $translation = new Translation();
        try {
            //We get all MichelangeloFE and PMDynaform translatable labels.
            $labels = array_merge(self::getLabelsMafe(), self::getLabelsPMDynaform());
            foreach ($labels as $label) {
                $translation->addTranslation('LABEL', 'ID_MAFE_' . G::encryptOld($label), 'en', $label);
            }
        } catch (Exception $e) {
            error_log($e->getMessage());
        }

        //creating the .po file
        $sPOFile = PATH_CORE . 'content' . PATH_SEP . 'translations' . PATH_SEP . MAIN_POFILE . '.' . $_GET['LOCALE'] . '.po';

        $poFile = new i18n_PO( $sPOFile );
        $poFile->buildInit();

        $language = new Language();

        $locale = $_GET['LOCALE'];
        $_TARGET_LANG = $_GET['LOCALE'];
        $_BASE_LANG = 'en';

        if (strpos( $locale, Translation::$localeSeparator ) !== false) {
            list ($LAN_ID, $IC_UID) = explode( Translation::$localeSeparator, $_GET['LOCALE'] );
            $iCountry = new IsoCountry();
            $iCountryRecord = $iCountry->findById( $IC_UID );

            if (! isset( $iCountryRecord['IC_UID'] )) {
                throw new Exception( "Country Target ID '{$_GET['LAN_ID']}' doesn't exist!" );
            }

            $sCountry = $iCountryRecord['IC_NAME'];
        } else {
            $LAN_ID = $locale;
            $sCountry = $IC_UID = '';
        }

        $langRecord = $language->findById( $LAN_ID );

        if (! isset( $langRecord['LAN_NAME'] )) {
            throw new Exception( "Language Target ID \"{$LAN_ID}\" doesn't exist!" );
        }

        $sLanguage = $langRecord['LAN_NAME'];

        //setting headers
        $poFile->addHeader( 'Project-Id-Version', 'ProcessMaker ' . System::getVersion() );
        $poFile->addHeader( 'POT-Creation-Date', '' );
        $poFile->addHeader( 'PO-Revision-Date', date( 'Y-m-d H:i:s' ) );
        $poFile->addHeader( 'Last-Translator', '' );
        $poFile->addHeader( 'Language-Team', 'Colosa Developers Team <developers@colosa.com>' );
        $poFile->addHeader( 'MIME-Version', '1.0' );
        $poFile->addHeader( 'Content-Type', 'text/plain; charset=utf-8' );
        $poFile->addHeader( 'Content-Transfer_Encoding', '8bit' );
        $poFile->addHeader( 'X-Poedit-Language', ucwords( $sLanguage ) );
        $poFile->addHeader( 'X-Poedit-Country', ucwords( $sCountry ) );
        $poFile->addHeader( 'X-Poedit-SourceCharset', 'utf-8' );
        $poFile->addHeader( 'Content-Transfer-Encoding', '8bit' );

        $aLabels = array ();
        $aMsgids = array ('' => true
        );

        // selecting all translations records of base language 'en' on TRANSLATIONS table
        $oCriteria = new Criteria( 'workflow' );
        $oCriteria->addSelectColumn( TranslationPeer::TRN_CATEGORY );
        $oCriteria->addSelectColumn( TranslationPeer::TRN_ID );
        $oCriteria->addSelectColumn( TranslationPeer::TRN_VALUE );
        $oCriteria->add( TranslationPeer::TRN_LANG, 'en' );
        $oDataset = TranslationPeer::doSelectRS( $oCriteria );
        $oDataset->setFetchmode( ResultSet::FETCHMODE_ASSOC );

        $targetLangRecords = array ();
        // retrieve the translation for the target language
        if ($LAN_ID != 'en') {
            // only if it is different language than base language 'en'
            $c = new Criteria( 'workflow' );
            $c->addSelectColumn( TranslationPeer::TRN_CATEGORY );
            $c->addSelectColumn( TranslationPeer::TRN_ID );
            $c->addSelectColumn( TranslationPeer::TRN_VALUE );
            $c->add( TranslationPeer::TRN_LANG, $_GET['LOCALE'] );
            $ds = TranslationPeer::doSelectRS( $c );
            $ds->setFetchmode( ResultSet::FETCHMODE_ASSOC );

            while ($ds->next()) {
                $row = $ds->getRow();
                $targetLangRecords[$row['TRN_CATEGORY'] . '/' . $row['TRN_ID']] = $row['TRN_VALUE'];
            }
        }

        // get the respective translation for each english label
        while ($oDataset->next()) {
            $aRow1 = $oDataset->getRow();
            $trnCategory = trim( $aRow1['TRN_CATEGORY'] );

            # Validation, validate that the TRN_CATEGORY contains valid characteres
            preg_match( "/^[0-9a-zA-Z_-]+/", $trnCategory, $sTestResult );

            // IF the translations id "TRN_ID" has invalid characteres or has not accepted categories
            if ($sTestResult[0] !== $trnCategory || ($trnCategory != 'LABEL' && $trnCategory != 'JAVASCRIPT')) {
                $translation->remove( $aRow1['TRN_CATEGORY'], $aRow1['TRN_ID'], 'en' ); //remove not accepted translations
                continue; //jump to next iteration
            }

            // retrieve the translation for the target language
            if ($LAN_ID != 'en') {
                // only if it is different language than base language 'en'
                if (isset( $targetLangRecords[$aRow1['TRN_CATEGORY'] . '/' . $aRow1['TRN_ID']] )) {
                    $msgstr = $targetLangRecords[$aRow1['TRN_CATEGORY'] . '/' . $aRow1['TRN_ID']] != '' ? $targetLangRecords[$aRow1['TRN_CATEGORY'] . '/' . $aRow1['TRN_ID']] : $aRow1['TRN_VALUE'];
                } else {
                    $msgstr = $aRow1['TRN_VALUE'];
                }
            } else {
                //if not just copy the same
                $msgstr = $aRow1['TRN_VALUE'];
            }

            $msgid = trim( $aRow1['TRN_VALUE'] );
            $msgstr = trim( $msgstr );

            if (isset( $aMsgids[$msgid] )) {
                $msgid = '[' . $aRow1['TRN_CATEGORY'] . '/' . $aRow1['TRN_ID'] . '] ' . $msgid;
            }

            $poFile->addTranslatorComment( 'TRANSLATION' );
            $poFile->addTranslatorComment( $aRow1['TRN_CATEGORY'] . '/' . $aRow1['TRN_ID'] );
            $poFile->addReference( $aRow1['TRN_CATEGORY'] . '/' . $aRow1['TRN_ID'] );

            $poFile->addTranslation( stripcslashes( $msgid ), stripcslashes( $msgstr ) );
            $aMsgids[$msgid] = true;
        }

        //$timer->setMarker('end making 1th .po from db');

        //find all xml files into PATH_XMLFORM
        $aXMLForms = glob( PATH_XMLFORM . '*/*.xml' );
        //from a sublevel to
        $aXMLForms2 = glob( PATH_XMLFORM . '*/*/*.xml' );
        $aXMLForms = array_merge( $aXMLForms, $aXMLForms2 );

        $aEnglishLabel = array ();
        $aOptions = array ();
        $nodesNames = Array ();



        foreach ($aXMLForms as $xmlFormPath) {
            $xmlFormFile = str_replace( chr( 92 ), '/', $xmlFormPath );
            $xmlFormFile = str_replace( PATH_XMLFORM, '', $xmlFormPath );

            $dynaForm = new DynaformHandler( $xmlFormPath );

            $dynaNodes = $dynaForm->getFields();

            //get all fields of each xmlform
            foreach ($dynaNodes as $oNode) {

                $sNodeName = $oNode->nodeName;
                //$arrayNode = $dynaForm->getArray($oNode, Array('type', $_BASE_LANG, $_BASE_LANG));
                $arrayNode = $dynaForm->getArray( $oNode );
                //if has not native language translation
                if (! isset( $arrayNode[$_BASE_LANG] ) || ! isset( $arrayNode['type'] ) || (isset( $arrayNode['type'] ) && in_array( $arrayNode['type'], $this->exceptionFields ))) {
                    continue; //just continue with the next node
                }

                // Getting the Base Origin Text
                if (! is_array( $arrayNode[$_BASE_LANG] )) {
                    $originNodeText = trim( $arrayNode[$_BASE_LANG] );
                } else {
                    $langNode = $arrayNode[$_BASE_LANG][0];
                    $originNodeText = $langNode['__nodeText__'];
                }

                // Getting the Base Target Text
                if (isset( $arrayNode[$_TARGET_LANG] )) {
                    if (! is_array( $arrayNode[$_TARGET_LANG] )) {
                        $targetNodeText = trim( $arrayNode[$_TARGET_LANG] );
                    } else {
                        $langNode = $arrayNode[$_TARGET_LANG][0];
                        $targetNodeText = $langNode['__nodeText__'];
                    }
                } else {
                    $targetNodeText = $originNodeText;
                }

                $nodeName = $arrayNode['__nodeName__'];
                $nodeType = $arrayNode['type'];

                $msgid = $originNodeText;

                // if the nodeName already exists in the po file, we need to create other msgid
                if (isset( $aMsgids[$msgid] )) {
                    $msgid = '[' . $xmlFormFile . '?' . $nodeName . '] ' . $originNodeText;
                }
                $poFile->addTranslatorComment( $xmlFormFile . '?' . $nodeName );
                $poFile->addTranslatorComment( $xmlFormFile );
                $poFile->addReference( $nodeType . ' - ' . $nodeName );
                $poFile->addTranslation( stripslashes( $msgid ), stripslashes( $targetNodeText ) );

                $aMsgids[$msgid] = true;

                //if this node has options child nodes
                if (isset( $arrayNode[$_BASE_LANG] ) && isset( $arrayNode[$_BASE_LANG][0] ) && isset( $arrayNode[$_BASE_LANG][0]['option'] )) {

                    $originOptionNode = $arrayNode[$_BASE_LANG][0]['option']; //get the options


                    $targetOptionExists = false;
                    if (isset( $arrayNode[$_TARGET_LANG] ) && isset( $arrayNode[$_TARGET_LANG][0] ) && isset( $arrayNode[$_TARGET_LANG][0]['option'] )) {
                        $targetOptionNode = $arrayNode[$_TARGET_LANG][0]['option'];
                        $targetOptionExists = true;
                    }

                    if (! is_array( $originOptionNode )) {
                        if (is_string( $originOptionNode )) {
                            $poFile->addTranslatorComment( $xmlFormFile . '?' . $nodeName . '-' . $originOptionNode );
                            $poFile->addTranslatorComment( $xmlFormFile );
                            $poFile->addReference( $nodeType . ' - ' . $nodeName . ' - ' . $originOptionNode );
                            $poFile->addTranslation( stripslashes( $msgid ), stripslashes( $originOptionNode ) );
                        }
                    } else {
                        foreach ($originOptionNode as $optionNode) {
                            $optionName = $optionNode['name'];
                            $originOptionValue = $optionNode['__nodeText__'];

                            if ($targetOptionExists) {

                                $targetOptionValue = getMatchDropdownOptionValue( $optionName, $targetOptionNode );
                                if ($targetOptionValue === false) {
                                    $targetOptionValue = $originOptionValue;
                                }
                            } else {
                                $targetOptionValue = $originOptionValue;
                            }

                            $msgid = '[' . $xmlFormFile . '?' . $nodeName . '-' . $optionName . ']';
                            $poFile->addTranslatorComment( $xmlFormFile . '?' . $nodeName . '-' . $optionName );
                            $poFile->addTranslatorComment( $xmlFormFile );
                            $poFile->addReference( $nodeType . ' - ' . $nodeName . ' - ' . $optionName );
                            $poFile->addTranslation( $msgid, stripslashes( $targetOptionValue ) );
                        }
                    }
                }
            } //end foreach
        }
        G::auditLog("ExportLanguage", "Language: ".$_GET['LOCALE']);
        G::streamFile( $sPOFile, true );
    }

    /**
     * Get Labels MAFE (Michelangelo Project)
     * @return array
     */
    public static function getLabelsMafe()
    {
        $labels = [];
        $buildhash = PATH_HTML . "lib/buildhash";
        if (!file_exists($buildhash)) {
            throw new RuntimeException("Unable to generate labels for MAFE!.\nMissing file '{$buildhash}'.");
        }
        $buildhash = file_get_contents($buildhash);

        $michelangeloFE = PATH_HTML . "lib/js";
        $array = glob($michelangeloFE . '/' . '*' . $buildhash . '*', GLOB_BRACE);
        $pathFileMafe = array_pop($array);
        if (file_exists($pathFileMafe) && is_readable($pathFileMafe)) {
            $labels = self::readLabelsDirectory($pathFileMafe, true);
        }
        return $labels;
    }

    /**
     * Get Labels PMDynaform (PMDynaform Project)
     * @return array
     */
    public static function getLabelsPMDynaform()
    {
        $labels = [];
        $pathFilePMDynaform = PATH_HTML . "lib/pmdynaform/build/js/PMDynaform.js";
        if (file_exists($pathFilePMDynaform) && is_readable($pathFilePMDynaform)) {
            $labels = self::readLabelsDirectory($pathFilePMDynaform, true);
        }
        return $labels;
    }

    /**
     * We read all labels
     * @param $path
     * @param bool $unique
     * @return array
     */
    public static function readLabelsDirectory($path, $unique = false)
    {
        $labels = [];
        if (is_file($path)) {
            $info = pathinfo($path);
            if (strtolower($info["extension"]) === "js") {
                $file = file_get_contents($path);
                //search string 'xx\'xx\'xx'.translate()
                $labels = array_merge($labels, self::readLabelsFile($file, "'"));
                //search string "xx\"xx\"xx".translate()
                $labels = array_merge($labels, self::readLabelsFile($file, "\""));
            }
        }
        if ($unique) {
            $labels = array_unique($labels);
        }
        return $labels;
    }

    public function updateLanguagePlugin ($plugin, $idLanguage)
    {
        if (!file_exists(PATH_PLUGINS . $plugin)) {
            throw new Exception( 'The plugin ' . $plugin . ' not exist' );
            die();
        }
        if (!file_exists(PATH_PLUGINS . $plugin . PATH_SEP . 'translations' . PATH_SEP . 'translations.php')) {
            throw new Exception( 'Translations.php not exist in plugin ' .  $plugin);
        }
        if (!file_exists(PATH_PLUGINS . $plugin . PATH_SEP . 'translations' . PATH_SEP . $plugin . '.' . $idLanguage . '.po')) {
            throw new Exception( 'The file ' . $plugin . '.' . $idLanguage . '.po not exists' );
            die();
        }
        $languageFile = PATH_PLUGINS . $plugin . PATH_SEP . 'translations' . PATH_SEP . $plugin . '.' . $idLanguage . '.po' ;
        try {

            $POFile = new i18n_PO( $languageFile );
            $POFile->readInit();
            $POHeaders = $POFile->getHeaders();

            $oTranslation = new Translation();
            $countItems = 0;
            $countItemsSuccess = 0;
            $errorMsg = '';

            while ($rowTranslation = $POFile->getTranslation()) {
                $countItems ++;
                if (! isset( $POFile->translatorComments[0] ) || ! isset( $POFile->translatorComments[1] ) || ! isset( $POFile->references[0] )) {
                    throw new Exception( 'The .po file doesn\'t have valid directives for Processmaker!' );
                }

                foreach ($POFile->translatorComments as $a => $aux) {
                    $identifier = '';
                    $context = '';
                    $aux = trim( $aux );
                    if ($aux == 'TRANSLATION') {
                        $identifier = $aux;
                    } else {
                        $var = explode( '/', $aux );
                        if ($var[0] == 'LABEL') {
                            $context = $aux;
                        }
                        if ($var[0] == 'JAVASCRIPT') {
                            $context = $aux;
                        }
                    }
                    if ($identifier == '' && $context == '') {
                        $context = $aux;
                    }
                    if (preg_match( '/^([\w-]+)\/([\w-]+\/*[\w-]*\.xml\?)/', $aux, $match )) {
                        $identifier = $aux;
                    } else {
                        if (preg_match( '/^([\w-]+)\/([\w-]+\/*[\w-]*\.xml$)/', $aux, $match )) {
                            $context = $aux;
                        }
                    }
                }

                $reference = $POFile->references[0];

                if ($identifier != 'TRANSLATION') {
                    $xmlForm = $context;
                    //erik: expresion to prevent and hable correctly dropdown values like -1, -2 etc.
                    preg_match( '/^([\w_]+)\s-\s([\w_]+)\s*-*\s*([\w\W]*)$/', $reference, $match );

                    if (! file_exists( PATH_PLUGINS . $plugin . PATH_SEP . $xmlForm )) {
                        $errorMsg .= 'file doesn\'t exist: ' . PATH_PLUGINS . $plugin . $xmlForm . "\n";
                        continue;
                    }

                    if (count( $match ) < 4) {
                        $near = isset( $rowTranslation['msgid'] ) ? $rowTranslation['msgid'] : (isset( $rowTranslation['msgstr'] ) ? $rowTranslation['msgstr'] : '');
                        $errorMsg .= "Invalid Translation reference: \"$reference\",  near -> " . strip_tags($near) . "\n";
                        continue;
                    }


                    $dynaform = new DynaformHandler( PATH_PLUGINS . $plugin . PATH_SEP . $xmlForm );
                    $fieldName = $match[2];

                    $codes = explode( '-', $reference );

                    if (sizeof( $codes ) == 2) {
                        //is a normal node
                        $dynaform->addChilds( $fieldName, Array ($idLanguage => stripcslashes( str_replace( chr( 10 ), '', $rowTranslation['msgstr'] ) )
                        ) );
                    } elseif (sizeof( $codes ) > 2) {
                        //is a node child for a language node
                        $name = $match[3] == "''" ? '' : $match[3];
                        $childNode = Array (
                            Array ('name' => 'option','value' => $rowTranslation['msgstr'],'attributes' =>
                                Array ('name' => $name)
                            )
                        );

                        $dynaform->addChilds( $fieldName, Array ($idLanguage => null
                        ), $childNode );
                    }
                    $countItemsSuccess ++;
                }
            }

            $trn = new Translation();
            $trn->generateFileTranslationPlugin( $plugin, $idLanguage );
            $trn->addTranslationEnvironmentPlugins( $plugin, $idLanguage, $POHeaders, $countItemsSuccess );
            $languageID = (isset($languageID)) ? $languageID : $idLanguage;

            //fill the results
            $results = new stdClass();
            $results->recordsCount = $countItems;
            $results->recordsCountSuccess = $countItemsSuccess;
            $results->lang = $languageID;
            $results->headers = $POHeaders;
            $results->errMsg = $errorMsg;

            return $results;
        } catch (Exception $oError) {
            throw ($oError);
        }
    }

    public function createLanguagePlugin ($plugin, $idLanguage)
    {
        if (!file_exists(PATH_PLUGINS . $plugin . PATH_SEP . 'translations' . PATH_SEP . 'translations.php')) {
            throw new Exception( 'Translation.php not exist in plugin ' .  $plugin);
        }

        $language = new Language();

        $locale = $language;
        $targetLang = $idLanguage;
        $baseLang = 'en';

        $aLabels = array ();
        $aMsgids = array ('' => true
        );
        include PATH_PLUGINS . $plugin . PATH_SEP . 'translations'. PATH_SEP . 'translations.php';
        $translatedText = array();

        if (file_exists( PATH_LANGUAGECONT . $plugin . "." . $idLanguage)) {
            //reading the .po file
            include PATH_LANGUAGECONT . $plugin . "." . $idLanguage;
            eval('$translatedText = $translation'.$plugin.';');
        }

        //creating the .po file
        $sPOFile = PATH_PLUGINS . $plugin . PATH_SEP . 'translations' . PATH_SEP . $plugin . '.' . $idLanguage . '.po';
        $poFile = new i18n_PO( $sPOFile );
        $poFile->buildInit();

        //setting headers
        $poFile->addHeader( 'Project-Id-Version', $plugin );
        $poFile->addHeader( 'POT-Creation-Date', '' );
        $poFile->addHeader( 'PO-Revision-Date', date( 'Y-m-d H:i:s' ) );
        $poFile->addHeader( 'Last-Translator', '' );
        $poFile->addHeader( 'Language-Team', 'Colosa Developers Team <developers@colosa.com>' );
        $poFile->addHeader( 'MIME-Version', '1.0' );
        $poFile->addHeader( 'Content-Type', 'text/plain; charset=utf-8' );
        $poFile->addHeader( 'Content-Transfer_Encoding', '8bit' );
        $poFile->addHeader( 'X-Poedit-Language', ucwords( $idLanguage ) );
        $poFile->addHeader( 'X-Poedit-SourceCharset', 'utf-8' );
        $poFile->addHeader( 'Content-Transfer-Encoding', '8bit' );


        foreach ($translations as $id => $translation) {
            $msgid = trim( $translation);
            $msgstr = trim( $translation );
            foreach ($translatedText as $key => $value) {
                if ($id == $key) {
                    $msgstr = trim( $value );
                    break;
                }
            }
            $poFile->addTranslatorComment( 'TRANSLATION' );
            $poFile->addTranslatorComment( 'LABEL/' . $id );
            $poFile->addReference( 'LABEL/'. $id );

            $poFile->addTranslation( stripcslashes( $msgid ), stripcslashes( $msgstr ) );
            $aMsgids[$msgid] = true;
        }

        $aXMLForms = glob( PATH_PLUGINS . $plugin . PATH_SEP  . '*.xml' );
        $aXMLForms2 = glob( PATH_PLUGINS . $plugin . PATH_SEP  . '*/*.xml' );
        $aXMLForms = array_merge( $aXMLForms, $aXMLForms2 );
        $aXMLForms3 = glob( PATH_PLUGINS . $plugin . PATH_SEP  . '*/*/*.xml' );
        $aXMLForms = array_merge( $aXMLForms, $aXMLForms3 );
        $aEnglishLabel = array ();
        $aOptions = array ();
        $nodesNames = Array ();



        foreach ($aXMLForms as $xmlFormPath) {
            $xmlFormFile = str_replace( chr( 92 ), '/', $xmlFormPath );
            $xmlFormFile = str_replace( PATH_PLUGINS . $plugin . PATH_SEP , '', $xmlFormPath );
            $dynaForm = new DynaformHandler( $xmlFormPath );
            $dynaNodes = $dynaForm->getFields();
            //get all fields of each xmlform
            foreach ($dynaNodes as $oNode) {
                $sNodeName = $oNode->nodeName;
                $arrayNode = $dynaForm->getArray( $oNode );
                //if has not native language translation
                if (! isset( $arrayNode[$baseLang] ) || ! isset( $arrayNode['type'] ) || (isset( $arrayNode['type'] ) && in_array( $arrayNode['type'], $this->exceptionFields ))) {
                    continue; //just continue with the next node
                }
                // Getting the Base Origin Text
                if (! is_array( $arrayNode[$baseLang] )) {
                    $originNodeText = trim( $arrayNode[$baseLang] );
                } else {
                    $langNode = $arrayNode[$baseLang][0];
                    $originNodeText = $langNode['__nodeText__'];
                }
                // Getting the Base Target Text
                if (isset( $arrayNode[$targetLang] )) {
                    if (! is_array( $arrayNode[$targetLang] )) {
                        $targetNodeText = trim( $arrayNode[$targetLang] );
                    } else {
                        $langNode = $arrayNode[$targetLang][0];
                        $targetNodeText = $langNode['__nodeText__'];
                    }
                } else {
                    $targetNodeText = $originNodeText;
                }
                $nodeName = $arrayNode['__nodeName__'];
                $nodeType = $arrayNode['type'];
                $msgid = $originNodeText;
                // if the nodeName already exists in the po file, we need to create other msgid
                if (isset( $aMsgids[$msgid] )) {
                    $msgid = '[' . $xmlFormFile . '?' . $nodeName . '] ' . $originNodeText;
                }
                $poFile->addTranslatorComment( $xmlFormFile . '?' . $nodeName );
                $poFile->addTranslatorComment( $xmlFormFile );
                $poFile->addReference( $nodeType . ' - ' . $nodeName );
                $poFile->addTranslation( stripslashes( $msgid ), stripslashes( $targetNodeText ) );

                $aMsgids[$msgid] = true;
                //if this node has options child nodes
                if (isset( $arrayNode[$baseLang] ) && isset( $arrayNode[$baseLang][0] ) && isset( $arrayNode[$baseLang][0]['option'] )) {
                    $originOptionNode = $arrayNode[$baseLang][0]['option']; //get the options
                    $targetOptionExists = false;
                    if (isset( $arrayNode[$targetLang] ) && isset( $arrayNode[$targetLang][0] ) && isset( $arrayNode[$targetLang][0]['option'] )) {
                        $targetOptionNode = $arrayNode[$targetLang][0]['option'];
                        $targetOptionExists = true;
                    }
                    if (! is_array( $originOptionNode )) {
                        if (is_string( $originOptionNode )) {
                            $poFile->addTranslatorComment( $xmlFormFile . '?' . $nodeName . '-' . $originOptionNode );
                            $poFile->addTranslatorComment( $xmlFormFile );
                            $poFile->addReference( $nodeType . ' - ' . $nodeName . ' - ' . $originOptionNode );
                            $poFile->addTranslation( stripslashes( $msgid ), stripslashes( $originOptionNode ) );
                        }
                    } else {
                        foreach ($originOptionNode as $optionNode) {
                            $optionName = $optionNode['name'];
                            $originOptionValue = $optionNode['__nodeText__'];
                            if ($targetOptionExists) {
                                $targetOptionValue = getMatchDropdownOptionValue( $optionName, $targetOptionNode );
                                if ($targetOptionValue === false) {
                                    $targetOptionValue = $originOptionValue;
                                }
                            } else {
                                $targetOptionValue = $originOptionValue;
                            }
                            $msgid = '[' . $xmlFormFile . '?' . $nodeName . '-' . $optionName . ']';
                            $poFile->addTranslatorComment( $xmlFormFile . '?' . $nodeName . '-' . $optionName );
                            $poFile->addTranslatorComment( $xmlFormFile );
                            $poFile->addReference( $nodeType . ' - ' . $nodeName . ' - ' . $optionName );
                            $poFile->addTranslation( $msgid, stripslashes( $targetOptionValue ) );
                        }
                    }
                }
            } //end foreach
        }
    }

    public static function readLabelsFile($file, $sep)
    {
        $labels = array();
        $k = 0;
        $j = 0;
        while ($j !== false) {
            $j = strpos($file, $sep . ".translate(", $k);
            if ($j !== false) {
                $k = $j + 1;
                $label = "";
                $j--;
                $c = substr($file, $j, 1);
                while (($c !== $sep || substr($file, $j - 1, 2) === "\\" . $sep) && $j > 0) {
                    $label = $c . $label;
                    $j--;
                    $c = substr($file, $j, 1);
                }
                if ($label !== "") {
                    if ($sep === "'") {
                        $label = str_replace("\'", "'", $label);
                    }
                    if ($sep === '"') {
                        $label = str_replace('\"', '"', $label);
                    }
                    array_push($labels, $label);
                }
            }
        }
        return $labels;
    }

    function loadByCode($langId) {
        try {
            $oCriteria = new Criteria('workflow');
            $oCriteria->addSelectColumn( LanguagePeer::LAN_NAME );
            $oCriteria->add(LanguagePeer::LAN_ID, $langId);
            $oDataset = LanguagePeer::doSelectRS($oCriteria);
            $oDataset->setFetchmode(ResultSet::FETCHMODE_ASSOC);
            $oDataset->next();
            $aRow = $oDataset->getRow();
            if (is_array($aRow)) {
                $aRow['LANGUAGE_NAME'] = $aRow['LAN_NAME'];
                return $aRow;
            } else {
                throw (new Exception("The language '$langId' doesn\'t exist!"));
            }
        } catch( exception $oError ) {
            throw ($oError);
        }
    }
}
// Language

function getMatchDropdownOptionValue ($name, $options)
{
    foreach ($options as $option) {
        if ($name == $option['name']) {
            return $option['__nodeText__'];
        }
    }
    return false;
}

