<?php
/**
 * Created by: Andrey Polyakov (andrey@polyakov.im)
 */

namespace Travelpayouts\components\base;

use Exception;
use Travelpayouts\components\BaseInjectedObject;
use Travelpayouts\traits\SingletonTrait;

/**
 * Class BasePluginCore
 * @package Travelpayouts\components\base
 */
abstract class BasePluginCore extends BaseInjectedObject
{
    use SingletonTrait;

    /**
     * @var string[]
     */
    public static $aliases = [];

    public function __construct($config = [])
    {
        self::$_instances[static::class] = $this;
        $this->registerAliases();
        parent::__construct($config);
    }

    /**
     * @return string[]
     */
    abstract protected function aliasList();

    protected function registerAliases()
    {
        $aliasList = $this->aliasList();
        foreach ($aliasList as $alias => $path) {
            self::setAlias($alias, $path);
        }
    }

    public static function getAlias($alias, $throwException = true)
    {
        if (strncmp($alias, '@', 1)) {
            return $alias;
        }
        $pos  = strpos($alias, '/');
        $root = $pos === false ? $alias : substr($alias, 0, $pos);
        if (isset(static::$aliases[$root])) {
            if (is_string(static::$aliases[$root])) {
                return $pos === false ? static::$aliases[$root] : static::$aliases[$root] . substr($alias, $pos);
            }
            foreach (static::$aliases[$root] as $name => $path) {
                if (strpos($alias . '/', $name . '/') === 0) {
                    return $path . substr($alias, strlen($name));
                }
            }
        }
        if ($throwException) {
            throw new Exception("Invalid path alias: $alias");
        }
        return false;
    }

    public static function setAlias($alias, $path)
    {
        if (strncmp($alias, '@', 1)) {
            $alias = '@' . $alias;
        }
        $pos  = strpos($alias, '/');
        $root = $pos === false ? $alias : substr($alias, 0, $pos);
        if ($path !== null) {
            $path = strncmp($path, '@', 1) ? rtrim($path, '\\/') : static::getAlias($path);
            if (!isset(static::$aliases[$root])) {
                if ($pos === false) {
                    static::$aliases[$root] = $path;
                } else {
                    static::$aliases[$root] = [$alias => $path];
                }
            } elseif (is_string(static::$aliases[$root])) {
                if ($pos === false) {
                    static::$aliases[$root] = $path;
                } else {
                    static::$aliases[$root] = [
                        $alias => $path,
                        $root  => static::$aliases[$root],
                    ];
                }
            } else {
                static::$aliases[$root][$alias] = $path;
                krsort(static::$aliases[$root]);
            }
        } elseif (isset(static::$aliases[$root])) {
            if (is_array(static::$aliases[$root])) {
                unset(static::$aliases[$root][$alias]);
            } elseif ($pos === false) {
                unset(static::$aliases[$root]);
            }
        }
    }

    /**
     * Translation helpers
     */

    public static function __($text, $params = [])
    {
        if (!did_action('init')) {
            return self::parse_message_params($text, $params);
        }

        $domain  = self::get_text_domain();
        $message = __($text, $domain);
        return self::parse_message_params($message, $params);
    }

    public static function esc_attr__($text, $params = [])
    {
        if (!did_action('init')) {
            return self::parse_message_params(esc_attr($text), $params);
        }

        $domain  = self::get_text_domain();
        $message = esc_attr__($text, $domain);
        return self::parse_message_params($message, $params);
    }

    public static function esc_html__($text, $params = [])
    {
        if (!did_action('init')) {
            return self::parse_message_params(esc_html($text), $params);
        }

        $domain  = self::get_text_domain();
        $message = esc_html__($text, $domain);
        return self::parse_message_params($message, $params);
    }

    public static function _e($text, $params = [])
    {
        if (!did_action('init')) {
            echo self::parse_message_params($text, $params);
            return;
        }

        $domain  = self::get_text_domain();
        $message = translate($text, $domain);
        echo self::parse_message_params($message, $params);
    }

    public static function esc_attr_e($text, $params = [])
    {
        if (!did_action('init')) {
            echo self::parse_message_params(esc_attr($text), $params);
            return;
        }

        $domain  = self::get_text_domain();
        $message = esc_attr(translate($text, $domain));
        echo self::parse_message_params($message, $params);
    }

    public static function esc_html_e($text, $params = [])
    {
        if (!did_action('init')) {
            echo self::parse_message_params(esc_html($text), $params);
            return;
        }

        $domain  = self::get_text_domain();
        $message = esc_html(translate($text, $domain));
        echo self::parse_message_params($message, $params);
    }

    public static function _x($text, $context, $params = [])
    {
        if (!did_action('init')) {
            return self::parse_message_params($text, $params);
        }

        $domain  = self::get_text_domain();
        $message = _x($text, $context, $domain);
        return self::parse_message_params($message, $params);
    }

    public static function _ex($text, $context, $params = [])
    {
        if (!did_action('init')) {
            echo self::parse_message_params($text, $params);
            return;
        }

        $domain  = self::get_text_domain();
        $message = _x($text, $context, $domain);
        echo self::parse_message_params($message, $params);
    }

    public static function esc_attr_x($text, $context, $params = [])
    {
        if (!did_action('init')) {
            return self::parse_message_params(esc_attr($text), $params);
        }

        $domain  = self::get_text_domain();
        $message = esc_attr_x($text, $context, $domain);
        return self::parse_message_params($message, $params);
    }

    public static function esc_html_x($text, $context, $params = [])
    {
        if (!did_action('init')) {
            return self::parse_message_params(esc_html($text), $params);
        }

        $domain  = self::get_text_domain();
        $message = esc_html_x($text, $context, $domain);
        return self::parse_message_params($message, $params);
    }

    public static function _n($single, $plural, $number, $params = [])
    {
        if (!did_action('init')) {
            $msg = ((int)$number === 1) ? $single : $plural;
            return self::parse_message_params($msg, $params);
        }

        $domain  = self::get_text_domain();
        $message = _n($single, $plural, $number, $domain);
        return self::parse_message_params($message, $params);
    }

    public static function _nx($single, $plural, $number, $context, $params = [])
    {
        if (!did_action('init')) {
            $msg = ((int)$number === 1) ? $single : $plural;
            return self::parse_message_params($msg, $params);
        }

        $domain  = self::get_text_domain();
        $message = _nx($single, $plural, $number, $context, $domain);
        return self::parse_message_params($message, $params);
    }

    public static function _n_noop($singular, $plural, $params = [])
    {
        if (!did_action('init')) {
            // noop: возвращаем структуру как WP _n_noop
            return [
                0 => $singular,
                1 => $plural,
                'singular' => $singular,
                'plural'   => $plural,
                'context'  => null,
                'domain'   => self::get_text_domain(),
            ];
        }

        $domain  = self::get_text_domain();
        $message = _n_noop($singular, $plural, $domain);
        return self::parse_message_params($message, $params);
    }

    public static function _nx_noop($singular, $plural, $context, $params = [])
    {
        if (!did_action('init')) {
            return [
                0 => $singular,
                1 => $plural,
                2 => $context,
                'singular' => $singular,
                'plural'   => $plural,
                'context'  => $context,
                'domain'   => self::get_text_domain(),
            ];
        }

        $domain  = self::get_text_domain();
        $message = _nx_noop($singular, $plural, $context, $domain);
        return self::parse_message_params($message, $params);
    }

    protected static function get_text_domain()
    {
        return TRAVELPAYOUTS_TEXT_DOMAIN;
    }

    protected static function parse_message_params($message, $params = [])
    {
        $placeholders = [];
        foreach ((array)$params as $name => $value) {
            $placeholders['{' . $name . '}'] = $value;
        }

        return ($placeholders === []) ? $message : strtr($message, $placeholders);
    }
}
