<?php

interface PolylangTranslatorInterface
{
    /**
     * @return bool
     */
    public function isInitialized();

    /**
     * @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());

    /**
     * @param string $text
     * @param string $from
     * @param string $to
     * @param array $options
     *
     * @return string|false
     */
    public function translateMIGXContent(string $text, string $from, string $to, array $options = array());

    /**
     * @param string $text
     *
     * @return false|string
     */

    public function detectLanguage(string $text);
}

abstract class PolylangTranslatorHandler implements PolylangTranslatorInterface
{
    /** @var modX */
    public $modx = null;
    /** @var Polylang */
    public $polylang = null;
    /**@var PolylangTools $tools */
    public $tools = null;
    /** @var array */
    public $config = array();
    /** @var bool */
    protected $isDetectSourceLanguage = false;
    protected $isPostProcessingTranslation = false;

    public function __construct(Polylang $polylang, $config = array())
    {
        $this->polylang = $polylang;
        $this->modx = $polylang->modx;
        $this->tools = $polylang->getTools();
        $this->config = array_merge($this->config, $config);
        $this->isDetectSourceLanguage = $this->modx->getOption('polylang_translate_detect_source_language', false);
        $this->isPostProcessingTranslation = $this->modx->getOption('polylang_post_processing_translation');
    }

    /**
     * @return bool
     */
    public function isInitialized()
    {
        return true;
    }

    /**
     * @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())
    {
        return $this->postProcessingTranslation($text);
    }

    public function translateMIGXContent(string $text, string $from, string $to, array $options = array())
    {
        return $text;
    }

    public function prepareTranslateMIGXItem(array $item): array
    {
        $texts = [];
        foreach ($item as $key => $value) {
            if ($key === 'MIGX_id') {
                continue;
            }
            $texts[] = $value;
        }
        return $texts;
    }


    /**
     * @param string $code
     *
     * @return string
     */
    public function prepareLanguageCode(string $code)
    {
        $code = $this->polylang->getTools()->prepareLanguageCode($code);
        if ($code == 'ua') {
            $code = 'uk';
        }
        return $code;
    }

    /**
     * @param string $text
     *
     * @return string
     */
    public function beforeTranslation(string $text)
    {
        if ($this->tools->isJSONStr($text)) {
            $text = $this->tools->normalizeJSONStr($text);
        }
        return $text;
    }

    /**
     * @param string $value
     *
     * @return bool
     */
    public function isMIGXContent(string $value): bool
    {
        return $this->tools->isMIGXContent($value);
    }


    /**
     * @param string $text
     *
     * @return string|bool
     */
    public function afterTranslation(string $text)
    {
        $beforeText = $text;
        if ($this->tools->isJSONStr($text)) {
            $text = htmlspecialchars_decode($text);
            $text = preg_replace_callback("/\"[^\"]+\"/", function ($value) {
                return '"' . trim($value[0], " \"") . '"';
            }, $text);
            $text = str_replace(array(' \ / ', '\ /', ' \/ \/ '), array('\/', '\/', '\/\/'), $text);
            $text = preg_replace_callback("|\w*(\s*\\\/\s*)\w*|", function ($value) {
                return str_replace(' ', '', $value[0]);
            }, $text);
            if (preg_match('/^\[?\{.+\}\]?/', $text, $matches)) {
                $text = $matches[0];
            }
            $beforeText = $text;
            $text = $this->tools->normalizeJSONStr($text);
        } else if ($this->isPostProcessingTranslation) {
            $text = $this->postProcessingTranslation($text);
        }
        if ($beforeText && (empty($text) || $text == '[]')) {
            return false;
        }
        return $text;
    }

    /**
     * @param string $text
     *
     * @return string
     */
    public function postProcessingTranslation(string $text)
    {
        if (empty($text)) return $text;

        $patterns = array(
            '/\[\[(\*|\$|\!)(\s+)(.*)\]\]/smi',
            '/&\s+(\w+)\s+=\s+`(.*)`/imu',
            '/`@\s+(FILE|TEMPLATE|INLINE|CODE)\s+(.*)`/imu',
            '/\$\s+\_\s?modx\s?->\s?/imu',
            '/\[\[~\s?\[\[\*\s?id\]\]\]\]/imu',
            '/\[\[([\*|%|~])\s+(\w+)\]\]/imu',
            '/\[\[\+\+\s+(\w+)\]\]/imu',
        );
        $replacements = array(
            '[[$1$3]]',
            '&$1=`$2`',
            '@$1 $2',
            '$modx->',
            '[[~[[*id]]]]',
            '[[$1$2]]',
            '[[++$1]]',
        );
        $text = preg_replace($patterns, $replacements, $text);

        $text = preg_replace_callback(
            '#`[^`]*@FILE[^`]+`#isu',
            function ($match) {
                return preg_replace('#\s+/\s+#isu', '/', $match[0]);
            },
            $text
        );

        $text = preg_replace_callback(
            '#\{[^\{].*[^\}]+\}#isu',
            function ($match) {
                return preg_replace('/(?<=\$)\s+/isu', '', $match[0]);
            },
            $text
        );

        return $text;
    }
}
