<?php

/**
 * @package         Convert Forms
 * @version         5.2.2 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\ListModel;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Factory;

class ConvertFormsModelForms extends ListModel
{
    /**
     *  File extension used for exported files
     *
     *  @var  string
     */
    private $fileExtension = ".cnvf";

    /**
     * Constructor.
     *
     * @param    array    An optional associative array of configuration settings.
     *
     * @see      JController
     */
    public function __construct($config = array())
    {
        if (empty($config['filter_fields']))
        {
            $config['filter_fields'] = array(
                'id', 'a.id',
                'state', 'a.state',
                'created', 'a.created',
                'ordering', 'a.ordering',
                'search',
                'name','a.name',
                'leads', 'issues'
            );
        }

        parent::__construct($config);
    }

    /**
     * Method to auto-populate the model state.
     *
     * This method should only be called once per instantiation and is designed
     * to be called on the first call to the getState() method unless the model
     * configuration flag to ignore the request is set.
     *
     * Note. Calling getState in this method will result in recursion.
     *
     * @param   string  $ordering   An optional ordering field.
     * @param   string  $direction  An optional direction (asc|desc).
     *
     * @return  void
     *
     * @since   3.7.0
     */
    protected function populateState($ordering = 'a.id', $direction = 'desc')
    {
        // List state information.
        parent::populateState($ordering, $direction);
    }

    /**
     * Method to build an SQL query to load the list data.
     *
     * @return      string  An SQL query
     */
    protected function getListQuery()
    {
        // Create a new query object.           
        $db = Factory::getDBO();
        $query = $db->getQuery(true);
        // Select some fields from the item table
        $query
            ->select('a.*')
            ->from('#__convertforms a');
        
        // Filter State
        $filter = $this->getState('filter.state');
        if (is_numeric($filter))
        {
            $query->where('a.state = ' . ( int ) $filter);
        }
        else if (is_array($filter))
        {
            $query->where('a.state IN (' . implode(',', $filter) . ')');
        }
        else if ($filter == '')
        {
            $query->whereIn(
                $db->quoteName('a.state'),
                [
                    0, 1,
                ]
            );
        }

        // Filter the list over the search string if set.
        $search = $this->getState('filter.search');
        if (!empty($search))
        {
            if (stripos($search, 'id:') === 0)
            {
                $query->where('a.id = ' . ( int ) substr($search, 3));
            }
            else
            {
                $search = $db->quote('%' . $db->escape($search, true) . '%');
                $query->where(
                    '( `name` LIKE ' . $search . ' )'
                );
            }
        }

        // Add the list ordering clause.
        $orderCol = $this->state->get('list.ordering', 'a.id');
        $orderDirn = $this->state->get('list.direction', 'desc');
        
        if ($orderCol == 'leads')
        {
            $query->select('(select count(submissions.id) from #__convertforms_conversions as submissions where submissions.form_id = a.id and submissions.state IN (1,2)) as leads');
        }

        $query->order($db->escape($orderCol . ' ' . $orderDirn));

        return $query;
    }

    /**
     * Import Method
     * Import the selected items specified by id
     * and set Redirection to the list of items
     */
    public function import($model)
    {
		$app = Factory::getApplication();

        $file = $app->input->files->get("file");

        if (!is_array($file) || !isset($file['name']))
        {
            $app->enqueueMessage(Text::_('NR_PLEASE_CHOOSE_A_VALID_FILE'));
            $app->redirect('index.php?option=com_convertforms&view=forms&layout=import');
        }

        $ext = explode(".", $file['name']);

        if ($ext[count($ext) - 1] != substr($this->fileExtension, 1))
        {
            $app->enqueueMessage(Text::_('NR_PLEASE_CHOOSE_A_VALID_FILE'));
            $app->redirect('index.php?option=com_convertforms&view=forms&layout=import');
        }

        jimport('joomla.filesystem.file');
        $publish_all = $app->input->getInt('publish_all', 0);

        $data = file_get_contents($file['tmp_name']);

        if (empty($data))
        {
            $app->enqueueMessage(Text::_('File is empty!'));
            $app->redirect('index.php?option=com_convertforms&view=forms');
            return;
        }
        
        $items = json_decode($data, true);
        if (is_null($items))
        {
            $items = array();
        }

        // Import plugins to allow them to handle import logic
        \Joomla\CMS\Plugin\PluginHelper::importPlugin('convertformstools');

        $saved = false;

        foreach ($items as $item)
        {
            $item['id'] = 0;
            if ($publish_all == 0)
            {
                unset($item['published']);
            }
            else if ($publish_all == 1)
            {
                $item['published'] = 1;
            }

            // Reset any error left over from a previous item so getError() reflects this item only
            $model->setError('');

            if (!$model->save($item))
            {
                $name  = isset($item['name']) && $item['name'] !== '' ? $item['name'] : Text::_('COM_CONVERTFORMS_UNTITLED_BOX');
                $error = $model->getError();

                $app->enqueueMessage(
                    $error
                        ? Text::sprintf('Could not import form <b>%s</b>: %s', $name, $error)
                        : Text::sprintf('Could not import form <b>%s</b>.', $name),
                    'error'
                );

                continue;
            }

            $saved = true;

            // Get the newly created form ID
            $newFormId = $model->getState('form.id');

            // Create form object with the imported data and new ID
            $formObject = (object) array_merge($item, ['id' => $newFormId]);

            // Trigger event for plugins to handle additional import logic (e.g., tasks, connections)
            Factory::getApplication()->triggerEvent('onConvertFormsImport', [$formObject]);
        }

        if ($saved)
        {
            $app->enqueueMessage(Text::_('Items saved'));
        }

        $app->redirect('index.php?option=com_convertforms&view=forms');
    }

    /**
     * Export Method
     * Export the selected items specified by id
     */
    public function export($ids)
    {
        $ids = array_values(array_filter(array_map('intval', (array) $ids)));

        if (!$ids)
        {
            return false;
        }

        $db    = $this->getDbo();
        $query = $db->getQuery(true)
            ->select('*')
            ->from('#__convertforms')
            ->where('id IN ( ' . implode(', ', $ids) . ' )');
        $db->setQuery($query);
        $rows = $db->loadObjectList();

        // Import plugins to allow them to add data to export
        \Joomla\CMS\Plugin\PluginHelper::importPlugin('convertformstools');

        // Trigger event for plugins to add additional data to export (e.g., tasks, connections)
        foreach ($rows as &$row)
        {
            Factory::getApplication()->triggerEvent('onConvertFormsExport', [&$row]);
        }

        $string = json_encode($rows);

        $filename = Text::_("COM_CONVERTFORMS") . ' Items';
        if (count($rows) == 1)
        {
            $name = Joomla\String\StringHelper::strtolower(html_entity_decode($rows['0']->name));
            $name = preg_replace('#[^a-z0-9_-]#', '_', $name);
            $name = trim(preg_replace('#__+#', '_', $name), '_-');

            $filename = Text::_("COM_CONVERTFORMS") .  ' Item (' . $name . ')';
        }

        // SET DOCUMENT HEADER
        if (preg_match('#Opera(/| )([0-9].[0-9]{1,2})#', $_SERVER['HTTP_USER_AGENT']))
        {
            $UserBrowser = "Opera";
        }
        elseif (preg_match('#MSIE ([0-9].[0-9]{1,2})#', $_SERVER['HTTP_USER_AGENT']))
        {
            $UserBrowser = "IE";
        }
        else
        {
            $UserBrowser = '';
        }
        $mime_type = ($UserBrowser == 'IE' || $UserBrowser == 'Opera') ? 'application/octetstream' : 'application/octet-stream';
        @ob_end_clean();
        ob_start();

        header('Content-Type: ' . $mime_type);
        header('Expires: ' . gmdate('D, d M Y H:i:s') . ' GMT');

        if ($UserBrowser == 'IE')
        {
            header('Content-Disposition: inline; filename="' . $filename . $this->fileExtension . '"');
            header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
            header('Pragma: public');
        }
        else
        {
            header('Content-Disposition: attachment; filename="' . $filename . $this->fileExtension . '"');
            header('Pragma: no-cache');
        }

        // PRINT STRING
        echo $string;
        die;
    }

    /**
     *  Returns Items Object and transforms params JSON field to object
     *
     *  @return  object
     */
    public function getItems()
    {
        $items = parent::getItems();

        foreach ($items as $key => $item)
        {
            $params = json_decode($item->params);
            $items[$key] = (object) array_merge((array) $item, (array) $params);
            unset($items[$key]->params);
        }

        return $items;
    }


}
