<?php

namespace Kanboard\Core;

/**
 * Translator class
 *
 * @package core
 * @author  Frederic Guillot
 */
class Translator
{
    /**
     * Locale path
     *
     * @var string
     */
    const PATH = 'app/Locale';

    /**
     * Locale
     *
     * @static
     * @access private
     * @var array
     */
    private static $locales = array();

    /**
     * Instance
     *
     * @static
     * @access private
     * @var Translator
     */
    private static $instance = null;

    /**
     * Get instance
     *
     * @static
     * @access public
     * @return Translator
     */
    public static function getInstance()
    {
        if (self::$instance === null) {
            self::$instance = new self;
        }

        return self::$instance;
    }

    /**
     * Get a translation
     *
     * $translator->translate('I have %d kids', 5);
     *
     * @access public
     * @param  string   $identifier       Default string
     * @return string
     */
    public function translate($identifier)
    {
        $args = func_get_args();

        array_shift($args);
        array_unshift($args, $this->get($identifier, $identifier));

        foreach ($args as &$arg) {
            $arg = htmlspecialchars($arg, ENT_QUOTES, 'UTF-8', false);
        }

        return call_user_func_array(
            'sprintf',
            $args
        );
    }

    /**
     * Get a translation with no HTML escaping
     *
     * $translator->translateNoEscaping('I have %d kids', 5);
     *
     * @access public
     * @param  string   $identifier       Default string
     * @return string
     */
    public function translateNoEscaping($identifier)
    {
        $args = func_get_args();

        array_shift($args);
        array_unshift($args, $this->get($identifier, $identifier));

        return call_user_func_array(
            'sprintf',
            $args
        );
    }

    /**
     * Get a formatted number
     *
     * $translator->number(1234.56);
     *
     * @access public
     * @param  float    $number   Number to format
     * @return string
     */
    public function number($number)
    {
        return number_format(
            $number,
            $this->get('number.decimals', 2),
            $this->get('number.decimals_separator', '.'),
            $this->get('number.thousands_separator', ',')
        );
    }

    /**
     * Get a formatted currency number
     *
     * $translator->currency(1234.56);
     *
     * @access public
     * @param  float    $amount   Number to format
     * @return string
     */
    public function currency($amount)
    {
        $position = $this->get('currency.position', 'before');
        $symbol = $this->get('currency.symbol', '$');
        $str = '';

        if ($position === 'before') {
            $str .= $symbol;
        }

        $str .= $this->number($amount);

        if ($position === 'after') {
            $str .= ' '.$symbol;
        }

        return $str;
    }

    /**
     * Get a formatted datetime
     *
     * $translator->datetime('%Y-%m-%d', time());
     *
     * @access public
     * @param  string   $format      Format defined by the strftime function
     * @param  integer  $timestamp   Unix timestamp
     * @return string
     */
    public function datetime($format, $timestamp)
    {
        if (! $timestamp) {
            return '';
        }

        $format = $this->get($format, $format);

        if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
            $format = str_replace('%e', '%d', $format);
            $format = str_replace('%k', '%H', $format);
        }

        return strftime($format, (int) $timestamp);
    }

    /**
     * Get an identifier from the translations or return the default
     *
     * @access public
     * @param  string   $identifier   Locale identifier
     * @param  string   $default      Default value
     * @return string
     */
    public function get($identifier, $default = '')
    {
        if (isset(self::$locales[$identifier])) {
            return self::$locales[$identifier];
        } else {
            return $default;
        }
    }

    /**
     * Load translations
     *
     * @static
     * @access public
     * @param  string   $language   Locale code: fr_FR
     * @param  string   $path       Locale folder
     */
    public static function load($language, $path = self::PATH)
    {
        setlocale(LC_TIME, $language.'.UTF-8', $language);

        $filename = $path.DIRECTORY_SEPARATOR.$language.DIRECTORY_SEPARATOR.'translations.php';

        if (file_exists($filename)) {
            self::$locales = array_merge(self::$locales, require($filename));
        }
    }

    /**
     * Clear locales stored in memory
     *
     * @static
     * @access public
     */
    public static function unload()
    {
        self::$locales = array();
    }
}