<?php

class PolylangTranslatorDeepl extends PolylangTranslatorHandler
{
    /** @var \DeepL\Translator|null $translator */
    public $translator = null;
    protected $deeplOptions = array();

    public function __construct(Polylang &$polylang, $config = array())
    {
        parent::__construct($polylang, $config);
        $key = $this->modx->getOption('polylang_translate_deepl_key', $config, '', true);
        if ($key) {
            try {
                $this->translator = new \DeepL\Translator($key);
                $options = $this->modx->getOption('polylang_translate_deepl_config', null, '{}', true);
                $this->deeplOptions = $this->tools->fromJSON($options, array());
            } catch (\DeepL\DeepLException $e) {
                $this->modx->log(modX::LOG_LEVEL_ERROR, $e->getMessage());
            }
        } else {
            $this->modx->log(modX::LOG_LEVEL_ERROR, 'Not set Deepl API key!');
        }
    }

    /**
     * @param string $text
     * @param string $from
     * @param string $to
     * @param array $options
     *
     * @return string|false
     */
    public function translate(string $text, string $from, string $to, array $options = array())
    {
        if (!$this->translator) return false;
        try {
            if ($text) {
                $from = $this->prepareLanguageCode($from);
                $to = $this->prepareLanguageTo($to);
                $text = $this->beforeTranslation($text);

                if ($this->isDetectSourceLanguage) {
                    if ($detectLang = $this->detectLanguage($text)) {
                        $from = $detectLang;

                        if ($this->tools->debug) {
                            $this->modx->log(modX::LOG_LEVEL_ERROR, "[Translate] Detected source language:{$from}");
                        }

                    }
                }
                if ($this->tools->isMIGXContent($text)) {
                    $text = $this->translateMIGXContent($text, $from, $to, $this->deeplOptions);
                } else {
                    $result = $this->translator->translateText($text, $from, $to, $this->deeplOptions);
                    $text = $this->afterTranslation($result->text);
                }

            }
        } catch (Exception $e) {
            $this->modx->log(modX::LOG_LEVEL_ERROR, $e->getMessage());
            return false;
        }
        return $text;
    }

    public function translateMIGXContent(string $text, string $from, string $to, array $options = array())
    {
        //[{"MIGX_id":"1","text":"Первый плюс", "text2":"Первый плюс"},{"MIGX_id":"2","text":"Второй плюс"}]
        $data = $this->tools->fromJSON($text);
        if (!$data) {
            return false;
        }

        foreach ($data as &$item) {
            $texts = $this->prepareTranslateMIGXItem($item);
            if (!$texts) {
                continue;
            }
            try {
                $index = 0;
                $translations = $this->translator->translateText($texts, $from, $to, $this->deeplOptions);
                foreach ($item as $key => &$text) {
                    if ($key === 'MIGX_id') {
                        continue;
                    }
                    if ($translations[$index]) {
                        $text = $translations[$index]->text;
                    }
                    $index++;
                }
            } catch (Exception $e) {
                $this->modx->log(modX::LOG_LEVEL_ERROR, $e->getMessage());
                return false;
            }
        }
        
        return json_encode($data, JSON_UNESCAPED_UNICODE);
    }

    /**
     * @param string $text
     *
     * @return false|string
     */
    public function detectLanguage(string $text)
    {
        if ($this->translator) {
            try {
                $result = $this->translator->translateText($text, null, 'en', $this->deeplOptions);
                if ($result) {
                    return $result->detectedSourceLang;
                }
            } catch (\DeepL\DeepLException $e) {
                $this->modx->log(modX::LOG_LEVEL_ERROR, 'Error detect language for text:' . $text);
            }
        }

        return false;
    }

    /**
     * @return bool
     */
    public function isInitialized()
    {
        return $this->translator !== null;
    }

    /**
     * @param string $to
     * @return string
     */
    protected function prepareLanguageTo(string $to)
    {
        $to = $this->prepareLanguageCode($to);
        switch ($to) {
            case 'en':
                $to = "{$to}-US";
                break;
            case 'pt':
                $to = "{$to}-BR";
                break;
        }
        return $to;
    }
}
