<?php

/**
 * Questo file è parte di Pongho.
 *
 * @author    Daniele De Nobili
 * @copyright Web Agency Meta Line S.r.l.
 * @package   Application\Admin
 */

namespace Application\Admin\Controller;

use Application\Core\Model\Settings;
use Pongho\Utilities\Inflector;

/**
 * Base per i controller che devono gestire delle opzioni.
 */
abstract class OptionsController extends AdminController
{
    /**
     * Restituisce il modello per la gestione delle opzioni.
     *
     * @return Settings
     */
    abstract public function getOptionsContainer();

    /**
     * {@inheritdoc}
     */
    protected function boot()
    {
        parent::boot();

        $this->getHelper()
            ->addCss(pongho_url(
                '/Application/Admin/Resources/views/css/style-legacy.css?v='
                . filemtime(PONGHO_PATH . '/Application/Admin/Resources/views/css/style-legacy.css')
            ));
    }

    /**
     * Elabora i campi passati per la visualizzazione ed il salvataggio.
     */
    protected function handleRequest(array $fields)
    {
        $container = $this->getOptionsContainer();
        $errors = [];

        if ($this->getRequest()->getMethod() === 'POST') {
            $post_options = isset($_POST['options']) && is_array($_POST['options']) ? $_POST['options'] : [];

            foreach ($fields as $field_name => $field_type) {
                $field_errors = [];

                $get_method = 'getField' . Inflector::camelize($field_type);
                $validate_method = 'validate' . Inflector::camelize($field_type);

                if (!method_exists($this, $get_method)) {
                    $get_method = 'getFieldText';
                }

                $field_value = $this->$get_method($post_options, $field_name, $container->getOption($field_name, null));

                if (method_exists($this, $validate_method)) {
                    $field_value = $this->$validate_method($field_value, $field_errors);
                }

                if ($field_errors === []) {
                    $container->setOption($field_name, $field_value);
                } else {
                    foreach ($field_errors as $error) {
                        $errors[] = $error;
                    }
                }
            }

            if (!$container->save()) {
                foreach ($container->errors->all_as_hash() as $error) {
                    $errors[] = $error;
                }
            }

            if ($errors === []) {
                $this->getHelper()->getBodyView()
                    ->assignVar(
                        'message',
                        $this->getHelper()->getTranslator()->trans('The options have been updated correctly.')
                    );
            } else {
                $this->getHelper()->getBodyView()
                    ->assignVar('errors', $errors);
            }
        }

        $vars = [];
        foreach ($fields as $field_name => $field_type) {
            $value = $container->getOption($field_name, null);

            if ($field_type === 'price') {
                $value = format_price($value, false);
            }

            $vars['value_' . $field_name] = $value;
        }

        $this->getHelper()->getBodyView()
            ->assignVars($vars);
    }

    /**
     * Elabora il POST di un campo booleano (solitamente checkbox) e restituisce il valore.
     *
     * @param string $field_name
     * @return bool
     */
    protected function getFieldBoolean(array $post_options, $field_name)
    {
        return isset($post_options[$field_name]) && $post_options[$field_name];
    }

    /**
     * Elabora il POST di un campo integer e restituisce il valore.
     *
     * @param string $field_name
     * @param mixed  $default
     * @return int
     */
    protected function getFieldInteger(array $post_options, $field_name, $default)
    {
        return isset($post_options[$field_name]) ? intval($post_options[$field_name]) : $default;
    }

    /**
     * Elabora il POST di un campo testo e restituisce il valore.
     *
     * @param string $field_name
     * @param mixed  $default
     * @return string
     */
    protected function getFieldText(array $post_options, $field_name, $default)
    {
        return isset($post_options[$field_name]) ? htmlspecialchars(trim($post_options[$field_name])) : $default;
    }

    /**
     * Elabora il POST di un campo testo e restituisce il valore.
     *
     * @param string $field_name
     * @param mixed  $default
     * @return string
     */
    protected function getFieldHtml(array $post_options, $field_name, $default)
    {
        return isset($post_options[$field_name]) ? trim($post_options[$field_name]) : $default;
    }

    /**
     * Elabora il POST di un campo password e restituisce il valore.
     *
     * @param string $field_name
     * @param mixed  $default
     * @return string
     */
    protected function getFieldPassword(array $post_options, $field_name, $default)
    {
        return isset($post_options[$field_name]) && !empty($post_options[$field_name]) ? htmlspecialchars(trim((string) $post_options[$field_name])) : $default;
    }

    /**
     * Elabora il POST di un campo prezzo e restituisce il valore.
     *
     * @param string $field_name
     * @param mixed  $default
     * @return float
     */
    protected function getFieldPrice(array $post_options, $field_name, $default)
    {
        return isset($post_options[$field_name]) ? parse_price($post_options[$field_name]) : $default;
    }
}
