<?php

use Joomla\CMS\Factory;
use Joomla\CMS\MVC\Controller\BaseController;
use Joomla\CMS\Router\Route;

// No direct access.
defined('_JEXEC') or die;

abstract class AbstractClubsController extends BaseController
{
    
    protected abstract function getNameOfElement();
    
    protected function getModelName()
    {
        return $this->getNameOfElement();
    }
    
    protected function getNameOfView()
    {
        return strtolower($this->getNameOfElement());
    }
    
    protected abstract function getDataMapping();
    
    function new()
    {
        $obj = call_user_func(array('Clubs' . $this->getNameOfElement(), 'create' . $this->getNameOfElement()));
        
        // Fetch the posted data
        $values = $this->loadData();

        $this->filterPreCheck($values);
        
        // Check the input data
        $error = $this->checkData($values);
        
        $view = $this->getNameOfView();
        
        if($error)
        {
            $urldata = $this->packData($values);
            $this->setRedirect(Route::_("index.php?option=com_clubs&view={$view}&id=new&data={$urldata}", false));
            return;
        }
        
        $this->applyData($obj, $values);
        
        // Do the actual work
        $obj->save();
        $this->setRedirect(Route::_("index.php?option=com_clubs&view={$view}s", false));
    }
    
    function change()
    {
        $app = Factory::getApplication();
        $input = $app->input;
        $id = (int) $input->post->getInt('id');
        
        $obj = call_user_func(array('Clubs' . $this->getNameOfElement(), 'load' . $this->getNameOfElement()), (int) $id);
        
        // Fetch the posted data
        $values = $this->loadData();
        
        $this->filterPreCheck($values);
        
        // Check the input data
        $error = $this->checkData($values);
        
        $view = $this->getNameOfView();
        
        if($error)
        {
            $urldata = $this->packData($values);
            $this->setRedirect(Route::_("index.php?option=com_clubs&view={$view}&id={$id}&data={$urldata}", false));
            return;
        }
        
        $this->applyData($obj, $values);
        
        // Do the actual work
        $obj->save();
        $this->setRedirect(Route::_("index.php?option=com_clubs&view={$view}s", false));
    }
    
    protected function loadData()
    {
        $values = array();
        $input = Factory::getApplication()->input->post;
        
        foreach($this->getDataMapping() as $m => $f)
        {
            $filter = (isset($f['filter'])) ? $f['filter'] : 'string';
            
            $values[$m] = $input->get($m, null, $filter);
        }
        
        return $values;
    }
    
    protected function filterPreCheck(&$values){}
    
    protected function checkData($values)
    {
        $error = false;
        // Check existence of the required fields
        foreach ($this->getDataMapping() as $m => $v)
        {
            if(! isset($v['required']) || ! $v['required'])
                continue;
            
            // Field is required
            if(! $this->fieldValid($m, $values[$m], $v))
            {
                $fname = (isset($v['name'])) ? $v['name'] : $m;
                Factory::getApplication()->enqueueMessage("Das Feld $fname ist obligatorisch.", 'error');
                $error = true;
            }
        }
        
        return $error;
    }
    
    protected function fieldValid($name, $value, $options)
    {
        if(empty($value))
            return false;
        
        if(isset($options['filter']))
        {
            switch($options['filter'])
            {
                case 'string':
                    if(empty(trim($value)))
                        return false;
            }
        }
        
        return true;
    }
    
    private function packData($values)
    {
        $data = array();
        foreach($this->getDataMapping() as $i)
            $data[$i] = $values[$i];
            
        return urlencode(json_encode($data));
    }
    
    public function applyData($obj, $values)
    {
        foreach($this->getDataMapping() as $m => $v)
        {
            $functionName = $this->getSetterMethodName($m, $v);
            $value = (isset($values[$m])) ? $values[$m] : null;
            $obj->$functionName($value);
        }
    }
    
    private function getSetterMethodName($m, $options)
    {
        if(isset($options['setter']))
            return $options['setter'];
        
        $firstChar = substr($m, 0, 1);
        $restChars = substr($m, 1);
        return 'set' . strtoupper($firstChar) . $restChars;
    }
    
    function delete()
    {
        $app = Factory::getApplication();
        
        $id = $app->input->get->getInt('id');
        $name = $this->getNameOfElement();
        $app->enqueueMessage("Removal of $name with id $id.");
        
        $className = 'Clubs' . $this->getModelName();
        $functionName = 'load' . $this->getModelName();
        $element = call_user_func(array($className, $functionName), $id);
        $element->delete();
        
        $view = $this->getNameOfView();
        $this->setRedirect(Route::_("index.php?option=com_clubs&view={$view}s", false));
    }
    
}