<?php

/**
 * @package         Convert Forms
 * @version         4.4.10 Free
 * 
 * @author          Tassos Marinos <info@tassos.gr>
 * @link            https://www.tassos.gr
 * @copyright       Copyright © 2024 Tassos All Rights Reserved
 * @license         GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
*/

defined('_JEXEC') or die('Restricted access');

use Joomla\CMS\MVC\Model\AdminModel;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\CMS\Table\Table;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Factory;
 
/**
 * Item Model
 */
class ConvertFormsModelForm extends AdminModel
{
    /**
     * Returns a reference to the a Table object, always creating it.
     *
     * @param       type    The table type to instantiate
     * @param       string  A prefix for the table class name. Optional.
     * @param       array   Configuration array for model. Optional.
     * @return      Table   A database object
     * @since       2.5
     */
    public function getTable($type = 'Form', $prefix = 'ConvertFormsTable', $config = array()) 
    {
        return Table::getInstance($type, $prefix, $config);
    }

    /**
     * Method to get the record form.
     *
     * @param       array   $data           Data for the form.
     * @param       boolean $loadData       True if the form is to load its own data (default case), false if not.
     * @return      mixed   A Form object on success, false on failure
     * @since       2.5
     */
    public function getForm($data = array(), $loadData = true) 
    {
        // Get the form.
        $form = $this->loadForm('com_convertforms.form', 'form', array('control' => 'jform', 'load_data' => $loadData));

        if (empty($form)) 
        {
            return false;
        }

        return $form;
    }

    protected function preprocessForm(Joomla\CMS\Form\Form $form, $data, $group = 'content')
    {
        $files = array(
            "form_design"
        );

        foreach ($files as $key => $value)
        {
            $form->loadFile($value, false);
        }

        // Call all ConvertForms plugins
        PluginHelper::importPlugin('convertforms');

        // load translation strings
        $this->loadTranslations();

        parent::preprocessForm($form, $data, $group);
    }
    
    /**
     * Enqueues translations for the back-end
     * 
     * @return  void
     */
    private function loadTranslations()
    {
        Text::script('COM_CONVERTFORMS_SUBMISSION');
        Text::script('COM_CONVERTFORMS_SUBMISSION_ID');
        Text::script('COM_CONVERTFORMS_SUBMISSION_DATE');
        Text::script('COM_CONVERTFORMS_SUBMISSION_USER_ID');
        Text::script('COM_CONVERTFORMS_SUBMISSION_STATUS');
        Text::script('COM_CONVERTFORMS_SUBMISSION_CAMPAIGN_ID');
        Text::script('COM_CONVERTFORMS_SUBMISSION_FORM_ID');
        Text::script('COM_CONVERTFORMS_SUBMISSION_VISITOR_ID');
        Text::script('COM_CONVERTFORMS_SUBMISSIONS_COUNT');
        Text::script('COM_CONVERTFORMS_FIELDS');
        Text::script('COM_CONVERTFORMS_ALL_FIELDS');
        Text::script('COM_CONVERTFORMS_ALL_FIELDS_NO_LABELS');
        Text::script('COM_CONVERTFORMS_ALL_FILLED_ONLY_FIELDS');
    }

    /**
     *  Prepare form fieldsets by tab into an array
     *
     *  @return  array
     */
    public function getTabs()
    {
        $form = $this->getForm();

        // Tabs
        $tabs = array(
           "fields" => array(
                "label" => "COM_CONVERTFORMS_FIELDS",
                "icon"  => "icon-list-2"
            ),
            "design" => array(
                "label" => "COM_CONVERTFORMS_DESIGN",
                "icon"  => "icon-picture"
            ),
            "behavior"   => array(
                "label" => "COM_CONVERTFORMS_BEHAVIOR",
                "icon"  => "icon-options"
            ),
            // This must be injected by the Tasks plugin somehow..
            'tasks'   => [
                "label" => "COM_CONVERTFORMS_TASKS",
                "icon"  => "icon-power-cord"
            ],
            "conversion" => array(
                "label" => "COM_CONVERTFORMS_SUBMISSION",
                "icon"  => "icon-generic"
            )
        );

        foreach ($tabs as $key => $tab)
        {
            $tabs[$key]["fields"] = $this->getFieldsetbyTab($form, $key);
        }

        return $tabs;
    }

    /**
     *  Return form fieldsets by tab attribute
     *
     *  @param   Form   $form  The form
     *  @param   string  $tab   The tab name
     *
     *  @return  array          Found fieldsets
     */
    private function getFieldsetbyTab($form, $tab)
    {
        $fieldsets = $form->getXML()->fieldset;

        $found = array();

        foreach ($fieldsets as $key => $fieldset)
        {
            if ($tab == (string) $fieldset["tab"])
            {
                $found[] = $fieldset;
            }
        }

        return $found;
    }

    public function getItem($pk = null)
    {
        if ($item = parent::getItem($pk)) {

            $params = $item->params;

            if (is_array($params) && count($params)) {

                foreach ($params as $key => $value) {
                    if (!isset($item->$key) && !is_object($value)) {
                        $item->$key = $value;
                    }
                }

                unset($item->params);
            }
        }

        return $item;
    }

    /**
     * Method to get the data that should be injected in the form.
     *
     * @return    mixed    The data for the form.
     */
    protected function loadFormData()
    {
        // Check the session for previously entered form data.
        $data = Factory::getApplication()->getUserState('com_convertforms.edit.form.data', array());

        if (!empty($data))
        {
            $params = json_decode($data['params'], true);
            $data   = array_merge($data, $params);
            unset($data['params']);

            return $data;
        }

        // Load existing form template
        if ($template = Factory::getApplication()->input->get('template', null))
        {
            if ($template = ConvertForms\Library::getTemplate($template))
            {
                return ConvertForms\Helper::prepareFormTemplate($template);
            }
        }

        if (empty($data))
        {
            $data = $this->getItem();

            if (is_null($data->name))
            {
                $data->name = Text::_('COM_CONVERTFORMS_UNTITLED_BOX');
            }
        }

        return $data;
    }

    /**
     * Method to save the form data.
     *
     * @param   array  The form data.
     *
     * @return  boolean  True on success.
     * @since   1.6
     */
    public function save($data)
    {
        $params = json_decode($data['params'], true);

        if (is_null($params))
        {
            $params = array();
        }

        // Validate field options
        foreach ($params['fields'] as $key => &$field)
        {
            if (!isset($field['type']))
            {
                continue;
            }

            $class = ConvertForms\FieldsHelper::getFieldClass($field['type']);

            if (!method_exists($class, 'onBeforeFormSave'))
            {
                continue;
            }

            if (!$class->onBeforeFormSave($this, $params, $field))
            {
                return false;
            }
        }

        $data['params'] = json_encode($params);

        return parent::save($data);
    }

    /**
     * Method to validate form data.
     */
    public function validate($form, $data, $group = null)
    {
        // Prevent saving form with an empty name
        if (empty($data["name"]))
        {
            $data["name"] = Text::_("COM_CONVERTFORMS_UNTITLED_BOX");
        }

        $newdata = array();
        
        $params = array();
        $this->_db->setQuery('SHOW COLUMNS FROM #__convertforms');
        $dbkeys = $this->_db->loadObjectList('Field');
        $dbkeys = array_keys($dbkeys);

        foreach ($data as $key => $val)
        {
            if (in_array($key, $dbkeys))
            {
                $newdata[$key] = $val;
            }
            else
            {
                $params[$key] = $val;
            }
        }

        $newdata['params'] = json_encode($params);
        return $newdata;
    }

    /**
     * Method to copy an item
     *
     * @access    public
     * @return    boolean    True on success
     */
    public function copy($id)
    {
        $item = $this->getItem($id);

        $item->id = 0;
        $item->published = 0;
        $item->name = Text::sprintf('NR_COPY_OF', $item->name);

        $item = $this->validate(null, get_object_vars($item));

        return ($this->save($item));
    }
}