<?php declare(strict_types=1);

require_once __DIR__ . '/../common/QrbException.php';

// Helper class for multi language texts.
final class QrbMultiLanguageText
{
    // key constants (public for unit tests)
    public const DEFAULT_KEY  = 'default';
    public const KEY_LANGUAGE = "language";
    public const KEY_TEXT     = "text";
    
    private array $text;
    
    // Validates a multi-language text from the given array.
    // The entries of the array are itself associative arrays and must contain the keys 
    // "language" and "text".
    // The key for the special language "default" **must** exist, and also the keys for the 
    // languages given in additionaLanguages **must** exist.
    public static function validate(string $itemName, array $jsonArray, array $additionalLanguages) : void
    {
        $texts = [];
        foreach ($jsonArray as $entry)
        {
            if (! array_key_exists(self::KEY_LANGUAGE, $entry))
                throw new QrbException(static::class . " - key 'language' does not exist",
                                       "exception.multiLanguageText.languageDoesNotExist",
                                       "{$itemName}");
            if (! array_key_exists(self::KEY_TEXT, $entry))
                throw new QrbException(static::class . " - key 'text' does not exist",
                                       "exception.multiLanguageText.textDoesNotExist",
                                       "{$itemName}");
            $texts[$entry[self::KEY_LANGUAGE]] = $entry[self::KEY_TEXT];
        }
        
        if (! array_key_exists(self::DEFAULT_KEY, $texts))
            throw new QrbException(static::class . ": language 'default' is missing in given texts.",
                                      "exception.multiLanguageText.defaultLanguageMissing",
                                      "{$itemName}");

        foreach ($additionalLanguages as $language)
        {
            if (! array_key_exists($language, $texts))
                throw new QrbException(static::class . ": language '{$language}' is missing in given texts.",
                                          "exception.multiLanguageText.additionalLanguageMissing",
                                          "{$itemName}, {$language}");
        }
    }
    
    // Creates a multi-language text from the given JSON array.
    // The entries of the array are itself associative arrays and must contain the keys 
    // "language" and "text".
    // Languages that are not present in the given supportedLanguages are ignored.
    // The special language code "default" must exist, and also the keys for the 
    // languages given in additionaLanguages **must** exist.
    public static function fromJsonArray(
            string $itemName,
            array  $jsonArray, 
            array  $supportedLanguages,
            array  $additionalLanguages
        ) : QrbMultiLanguageText
    {
        self::validate($itemName, $jsonArray, $additionalLanguages);
        
        $texts = [];
        foreach ($jsonArray as $entry)
        {
            if (  ($entry[self::KEY_LANGUAGE] != self::DEFAULT_KEY)
               && (! in_array($entry[self::KEY_LANGUAGE], $supportedLanguages)))
            {
                continue;
            }
            
            $texts[$entry[self::KEY_LANGUAGE]] = $entry[self::KEY_TEXT];
        }
        
        $mlText = new self($texts[self::DEFAULT_KEY]);
                
        foreach ($texts as $key => $text)
        {
            if ($key != self::DEFAULT_KEY)    // already in by constructor
            {
                $mlText->addText($key, $text);
            }
        }
        
        return $mlText;
    }
    
    // Stores the given multi-langauge text in a JSON array, embedded in the given key "itemName". 
    public static function toJsonArray(QrbMultiLanguageText $mlText, string $itemName) : array
    {
        $innerArray = array();
        foreach ($mlText->getTexts() as $key => $value)
        {
            $entry = array();
            $entry[self::KEY_LANGUAGE] = $key;
            $entry[self::KEY_TEXT]     = $value;
            array_push($innerArray, $entry);
        }
        
        $jsonArray = array();
        $jsonArray[$itemName] = $innerArray;
        return $jsonArray;
    }
    
    // Creates a multi-language text with the given default text.
    public function __construct(string $defaultText)
    {
        $this->text[self::DEFAULT_KEY] = $defaultText;
    }
    
    // Adds the given text in the given language.
    public function addText(string $language, string $text) : void
    {
        $this->text[$language] = $text;
    }
    
    // Checks whether there exists a localized text in the given language.
    public function existsLocalizedText(string $language) : bool
    {
        return array_key_exists($language, $this->text) ? true : false;
    }
    
    // Returns the text in the given language 
    // or (if the given language is NULL or the text has not been found in the given language) 
    // the default text.
    public function getText(string $language) : string
    {
        if (  ($language != NULL)
           && array_key_exists($language, $this->text) )
        {
            return $this->text[$language];
        }
        
        return $this->text[self::DEFAULT_KEY];
    }
    
    public function getTexts() : array
    {
        return $this->text;
    }
    
    public function __toString() : string
    {
        $returnValue = "\n";
        
        foreach($this->text as $key => $value)
        {
            $returnValue .= "\tKey = '{$key}', Value = '{$value}'\n";
        }
    
        // delete last '\n'
        return substr($returnValue, 0, -1);
    }
}

?>
