<?php

namespace Velis\Model\DataObject;

use Velis\Arrays;
use Velis\DictionaryEntry;
use Velis\Filter;
use Velis\Lang;
use Velis\Model\DataObject;
use Velis\Output;

/**
 * Utility functions trait
 * @author Olek Procki <olo@velis.pl>
 */
trait UtilityTrait
{
    /**
     * Set true for looking for name column in listDatasource
     * @var bool
     */
    protected static $_getNameFromSource = false;


    /**
     * Returns translated name
     * @param $fieldName string
     */
    public function getTranslatedName($fieldName = 'name', $defValue = null, $checkAppLangs = true)
    {
        $suggestedTranslations = [
            'userLang' => $fieldName . '_' . Lang::getLanguage(),
            'appLang' => $fieldName . '_' . Lang::getDefaultLanguage(),
            'fieldEnTranslate' => $fieldName . '_en',
            'ifFieldIsNotAppLang' => !$this->fieldTypeIsAppLang($fieldName) ? $fieldName : null
        ];

        if ($checkAppLangs) {
            foreach (Lang::getLanguages() as $languageCode => $languageName) {
                $suggestedTranslations['lang_' . $languageCode] = $fieldName . '_' . $languageCode;
            }
        }

        foreach ($suggestedTranslations as $suggestedTranslation) {
            if (!empty($this[$suggestedTranslation])) {
                return $this[$suggestedTranslation];
            }
        }
        return $defValue;
    }
    /**
     * set default translation
     * @param $field string
     */
    public function setDefaultTranslation($field = 'name')
    {
        $defaultTranslationFieldName = $field . '_' . Lang::getDefaultLanguage();
        $userDefinedTranslation = $field . '_' . Lang::getLanguage();
        if (isset($this[$defaultTranslationFieldName]) && empty($this[$defaultTranslationFieldName])) {
            $this[$defaultTranslationFieldName] = $this[$userDefinedTranslation];
        }
    }

    /**
     * Check if field is app.lang
     * @param $fieldName string
     * @return boolean;
     */
    public function fieldTypeIsAppLang($fieldName)
    {
        $instance = new static();

        if ($instance instanceof DictionaryEntry) {
            return false;
        }

        $source = $instance::$_getNameFromSource ? $instance->_getDetailsDatasource() : $instance->_getTableName();
        $columns  = self::$_db->getColumns($source);
        return array_key_exists($fieldName, Arrays::byValue($columns, 'data_type', 'USER-DEFINED'));
    }

    /**
    * @param string $fieldName
    * Returns array from field values
    * @return array
    */
    public function fieldToArray($fieldName)
    {
        return self::dataToArray($this[$fieldName]);
    }

    /**
    * @param string $data
    * Returns array from string
    * @return array
    */
    public static function dataToArray($data): array
    {
        return array_filter(
            Arrays::filterKeepZeros(explode(',', trim($data, '{}'))),
            fn ($val) => $val !== 'NULL'
        );
    }

    /**
     * Convert array to PostgreSQL array
     * @param array $data
     */
    public static function arrayToPgArray(array $data): string
    {
        return '{' . implode(',', $data) . '}';
    }

    /**
    * @param string $string
    * replaces placeholders to object field values
    * @return string
    */
    public function translatePlaceholders($string)
    {
        preg_match_all("/\{([^\}]*)\}/", $string, $placeholders);

        foreach ($placeholders[0] as $placeholder) {
            $field = trim($placeholder, '{}');
            $objectField = strtolower(Output::toSnakeCase($field));

            if (method_exists($this, 'get' . $field)) {
                $replace = (string) $this->{'get' . $field}();
            } elseif ($this->offsetExists($objectField)) {
                $replace = (string) $this[$objectField];
            } else {
                continue;
            }

            if (!strlen($replace)) {
                $replace = Lang::get('GENERAL_LACK_2');
            }

            if ($objectField == 'description') {
                $replace = Filter::filterTextile($replace);
            }

            $string = str_replace($placeholder, $replace, $string);
        }
        return $string;
    }


    /**
     * Build path dir by id
     * @return string
     */
    public function getPathById()
    {
        $x = ( $this->id() - ($this->id() % 1000) );
        if ($x == '0') {
            return '0/';
        }
        return ($x / 1000 ) . '/';
    }

    /**
     * @param DataObject|array<string, mixed> $object
     */
    protected static function getStaticClassInstance($object): static
    {
        $class = static::class;
        if (!is_object($object) || get_class($object) != $class) {
            $object = new $class($object);
        }

        return $object;
    }
}
