<?php

/*
  __PocketMine Plugin__
  name=PMTranslator
  description=Translate stuff in-game!
  version=1.0
  author=tschrock
  class=PMTranslator
  apiversion=12
 */

class PMTranslator implements Plugin {

    private $api, $config;
    public $returnArray;

    public function __construct(ServerAPI $api, $server = false) {
        $this->api = $api;
        $this->returnArray = new SharedArray(Array());
        TranslateAPI::set($this);
    }

    public function init() {

        $this->config = new Config($this->api->plugin->configPath($this) . "config.yml", CONFIG_YAML, array(
            "baseUrl" => "http://translate.google.com/translate_a/t?client=p&ie=UTF-8&oe=UTF-8",
            "defaultTo" => "en",
            "defaultFrom" => "auto",
            "UserAgent" => "Mozilla/4.0"
        ));

        $this->api->schedule(20, array($this, "timeHandler"), array(), true);
        $this->api->console->register("translate", "/translate (lang) to <lang> <Text to translate>", array($this, "commandHandler"));
    }

    public function timeHandler() {
        foreach ($this->returnArray as $key => $result) {
            if ($result[0] == 'console') {
                console($result[1]);
            } else {
                if ($play = $this->api->player->get($result[0])){
                    $play->sendChat($result[1]);
                }
            }
            unset($this->returnArray[$key]);
        }
    }

    public function commandHandler($cmd, $params, $issuer) {
        if ($cmd == "translate") {
            if ($params[0] == "to") {
                $fromlang = $this->config->get("defaultFrom");
                $tolang = $params[1];
                $offset = 2;
            } elseif ($params[1] == "to") {
                $fromlang = $params[0];
                $tolang = $params[2];
                $offset = 3;
            } else {
                $fromlang = $this->config->get("defaultFrom");
                $tolang = $this->config->get("defaultTo");
                $offset = 0;
            }
            $player = ($issuer instanceof Player)? $issuer->iusername : 'console';
            return $this->translate(implode(" ", array_slice($params, $offset)), $tolang, $fromlang, $player);
        }
    }

    public function translate($text, $langTo, $langFrom, $player = "console") {
        $langTo = TranslateAPI::parseLang($langTo);
        $langFrom = TranslateAPI::parseLang($langFrom);

        $translateurl = $this->config->get("baseUrl") . "&text=" . urlencode($text) . "&hl=$langTo&sl=$langFrom";

        $curlReq = curl_init($translateurl);
        curl_setopt($curlReq, CURLOPT_USERAGENT, $this->config->get("UserAgent"));
        curl_setopt($curlReq, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curlReq, CURLOPT_FAILONERROR, true);

        $thrd = new TranslatorCurlThread($this->returnArray, $player, $curlReq);
        $thrd->start();
    }

    public function __destruct() {
        
    }
    
    public function updateReturn($arr){
        $this->returnArray = $arr;
    }
    

}

class TranslateAPI {

    private static $object;

    public static function set(PMTranslator $plugin) {
        if (TranslateAPI::$object instanceof Translator) {
            return false;
        }
        TranslateAPI::$object = $plugin;
    }

    public static function get() {
        return TranslateAPI::$object;
    }

    public static function translate($text, $langTo, $langFrom, $player) {
        return TranslateAPI::$object->translate($text, $langTo, $langFrom, $player);
    }

    public static function parseLang($language) {
        $lang = array_search(strtolower($language), TranslateAPI::$langCodes);
        if (is_null($lang) || $lang === false) {
            $lang = $language;
        }
        return $lang;
    }

    private static $langCodes = array(
        "af" => "afrikaans",
        "ak" => "akan",
        "sq" => "albanian",
        "am" => "amharic",
        "ar" => "arabic",
        "hy" => "armenian",
        "az" => "azerbaijani",
        "eu" => "basque",
        "be" => "belarusian",
        "bem" => "bemba",
        "bn" => "bengali",
        "bh" => "bihari",
        "xx-bork" => "bork",
        "bs" => "bosnian",
        "br" => "breton",
        "bg" => "bulgarian",
        "km" => "cambodian",
        "ca" => "catalan",
        "chr" => "cherokee",
        "ny" => "chichewa",
        "zh-cn" => "chinese_simplified",
        "zh-tW" => "chinese_traditional",
        "co" => "corsican",
        "hr" => "croatian",
        "cs" => "czech",
        "da" => "danish",
        "nl" => "dutch",
        "xx-elmer" => "elmer_fudd",
        "en" => "english",
        "eo" => "esperanto",
        "et" => "estonian",
        "ee" => "ewe",
        "fo" => "faroese",
        "tl" => "filipino",
        "fi" => "finnish",
        "fr" => "french",
        "fy" => "frisian",
        "gaa" => "ga",
        "gl" => "galician",
        "ka" => "georgian",
        "de" => "german",
        "el" => "greek",
        "gn" => "guarani",
        "gu" => "gujarati",
        "xx-hacker" => "hacker",
        "ht" => "haitian_creole",
        "ha" => "hausa",
        "haw" => "hawaiian",
        "iw" => "hebrew",
        "hi" => "hindi",
        "hu" => "hungarian",
        "is" => "icelandic",
        "ig" => "igbo",
        "id" => "indonesian",
        "ia" => "interlingua",
        "ga" => "irish",
        "it" => "italian",
        "ja" => "japanese",
        "jw" => "javanese",
        "kn" => "kannada",
        "kk" => "kazakh",
        "rw" => "kinyarwanda",
        "rn" => "kirundi",
        "xx-klingon" => "klingon",
        "kg" => "kongo",
        "ko" => "korean",
        "kri" => "krio",
        "ku" => "kurdish",
        "ckb" => "kurdish_soranî",
        "ky" => "kyrgyz",
        "lo" => "laothian",
        "la" => "latin",
        "lv" => "latvian",
        "ln" => "lingala",
        "lt" => "lithuanian",
        "loz" => "lozi",
        "lg" => "luganda",
        "ach" => "luo",
        "mk" => "macedonian",
        "mg" => "malagasy",
        "ms" => "malay",
        "ml" => "malayalam",
        "mt" => "maltese",
        "mi" => "maori",
        "mr" => "marathi",
        "mfe" => "mauritian_creole",
        "mo" => "moldavian",
        "mn" => "mongolian",
        "sr-me" => "montenegrin",
        "ne" => "nepali",
        "pcm" => "nigerian_pidgin",
        "nso" => "northern_sotho",
        "no" => "norwegian",
        "nn" => "norwegian_nynorsk",
        "oc" => "occitan",
        "or" => "oriya",
        "om" => "oromo",
        "ps" => "pashto",
        "fa" => "persian",
        "xx-pirate" => "pirate",
        "pl" => "polish",
        "pt-br" => "portuguese_brazil",
        "pt-pt" => "portuguese",
        "pa" => "punjabi",
        "qu" => "quechua",
        "ro" => "romanian",
        "rm" => "romansh",
        "nyn" => "runyakitara",
        "ru" => "russian",
        "gd" => "scots_gaelic",
        "sr" => "serbian",
        "sh" => "serbo-croatian",
        "st" => "sesotho",
        "tn" => "setswana",
        "crs" => "seychellois_creole",
        "sn" => "shona",
        "sd" => "sindhi",
        "si" => "sinhalese",
        "sk" => "slovak",
        "sl" => "slovenian",
        "so" => "somali",
        "es" => "spanish",
        "es-419" => "spanish_latin_american",
        "su" => "sundanese",
        "sw" => "swahili",
        "sv" => "swedish",
        "tg" => "tajik",
        "ta" => "tamil",
        "tt" => "tatar",
        "te" => "telugu",
        "th" => "thai",
        "ti" => "tigrinya",
        "to" => "tonga",
        "lua" => "tshiluba",
        "tum" => "tumbuka",
        "tr" => "turkish",
        "tk" => "turkmen",
        "tw" => "twi",
        "ug" => "uighur",
        "uk" => "ukrainian",
        "ur" => "urdu",
        "uz" => "uzbek",
        "vi" => "vietnamese",
        "cy" => "welsh",
        "wo" => "wolof",
        "xh" => "xhosa",
        "yi" => "yiddish",
        "yo" => "yoruba",
        "zu" => "zulu"
    );

}

class SharedArray extends Stackable {

    public function __construct($array) {
        $this->merge($array);
    }

    public function run() {
        
    }

}

class TranslatorCurlThread extends Thread {

    private $curlRequest;
    public $returnArray;
    private $playerName;

    public function __construct(SharedArray $return, $playerName, $curlRequest) {
        $this->curlRequest = $curlRequest;
        $this->returnArray = $return;
        $this->playerName = $playerName;
    }

    function run() {

        $result = curl_exec($this->curlRequest);
        curl_close($this->curlRequest);

        if ($result === false || !is_string($result)) {
            $this->returnArray[] = Array($this->playerName, "Could not translate text");
        } else {
            $Jdecode = json_decode($result, true);

            if (!is_null($Jdecode) && isset($Jdecode["sentences"]) && isset($Jdecode["sentences"][0]) && isset($Jdecode["sentences"][0]["trans"])) {
                $this->returnArray[] = Array($this->playerName, $Jdecode["sentences"][0]["trans"]);
            } else {
                $this->returnArray[] = Array($this->playerName, "Could not translate text");
            }
        }
        
    }

}
