<?php
/**
* @package   Gridbox
* @author    Balbooa http://www.balbooa.com/
* @copyright Copyright @ Balbooa
* @license   http://www.gnu.org/licenses/gpl.html GNU/GPL
*/

namespace Balbooa\Component\Gridbox\Administrator\Model;

defined('_JEXEC') or die;

use Balbooa\Component\Gridbox\Administrator\Helper\GridboxHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\MVC\Model\ListModel;

class PagesModel extends ListModel
{
    public function __construct($config = [])
    {
        if (empty($config['filter_fields'])) {
            $config['filter_fields'] = [
                'id', 'title', 'published', 'theme', 'state', 'created', 'hits', 'order_list'
            ];
        }
        parent::__construct($config);
    }

    public function setGridboxFilters()
    {
        /**
         * @var Joomla\CMS\Application\AdministratorApplication
         */
        $app = Factory::getApplication();
        $ordering = $app->getUserStateFromRequest($this->context . '.ordercol', 'filter_order', null);
        $direction = $app->getUserStateFromRequest($this->context . '.orderdirn', 'filter_order_Dir', null);
        GridboxHelper::setGridboxFilters($ordering, $direction, $this->context);
    }

    public function getGridboxFilters()
    {
        $array = GridboxHelper::getGridboxFilters($this->context);
        if (!empty($array)) {
            foreach ($array as $obj) {
                $name = str_replace($this->context.'.', '', $obj->name);
                $this->setState($name, $obj->value);
            }
        }
    }

    public function setFilters()
    {
        $this->setGridboxFilters();
        $this->populateState();
    }
    
    protected function getListQuery()
    {
        $this->getGridboxFilters();
        $app = Factory::getApplication();
        $db = Factory::getDbo();
        $layout = $app->input->get('layout', '');
        if ($layout != 'apps' && $layout != 'modal') {
            $query = $db->getQuery(true)
                ->select('id')
                ->from('#__gridbox_pages')
                ->where('`app_id` = 0')
                ->where('`order_list` = 0')
                ->where('`page_category` <> '.$db->Quote('trashed'))
                ->where('(published IN (0, 1))');
            $db->setQuery($query);
            $items = $db->loadObjectList();
            if (!empty($items)) {
                $query = $db->getQuery(true)
                    ->select('MAX(order_list) as max, COUNT(id) as count')
                    ->from('#__gridbox_pages')
                    ->where('`app_id` = 0')
                    ->where('`order_list` <> 0')
                    ->where('`page_category` <>'.$db->Quote('trashed'))
                    ->where('(published IN (0, 1))');
                $db->setQuery($query);
                $obj = $db->loadObject();
                if ($obj->count == 0) {
                    $obj->max = 0;
                }
                foreach ($items as $value) {
                    $value->order_list = ++$obj->max;
                    $db->updateObject('#__gridbox_pages', $value, 'id');
                }
            }
        }
        $query = $db->getQuery(true);
        if ($layout == 'apps') {
            $query->select('title, id')
                ->from('#__gridbox_app')
                ->where('type <> '.$db->quote('system_apps'))
                ->order($db->escape('order_list DESC'));
            $search = $this->getState('filter.search');
            if (!empty($search)) {
                $search = $db->quote('%' . $db->escape($search, true) . '%', false);
                $query->where('title LIKE ' . $search);
            }

            return $query;
        } else if ($layout == 'modal') {
            $id = $app->input->get('id', 0);
            $query->select('title, id')
                ->from('#__gridbox_pages')
                ->where('published = 1')
                ->where('page_category <>'.$db->quote('trashed'))
                ->where('app_id = '.$id)
                ->order($db->escape('id asc'));
            $search = $this->getState('filter.search');
            if (!empty($search)) {
                $search = $db->quote('%' . $db->escape($search, true) . '%', false);
                $query->where('title LIKE ' . $search);
            }

            return $query;
        }
        $this->checkThemes();
        $query->select('p.id, p.title, p.theme, p.published, p.meta_title, p.meta_description,
            p.robots, p.schema_markup, p.meta_keywords, p.intro_image, p.page_alias,
            p.page_category, p.end_publishing, p.share_image, p.share_title,
            p.share_description, p.page_access, p.intro_text, p.created, p.language,
            p.hits, p.order_list, p.class_suffix, p.sitemap_override,
            p.sitemap_include, p.changefreq, p.priority, t.title AS themeName')
            ->from('#__gridbox_pages as p')
            ->where('`app_id` = 0')
            ->where('`page_category` <>'.$db->quote('trashed'))
            ->leftJoin('#__template_styles AS t ON p.theme = t.id');
        $search = $this->getState('filter.search');
        if (!empty($search)) {
            $search = $db->quote('%' . $db->escape($search, true) . '%', false);
            $query->where('p.title LIKE ' . $search);
        }
        $published = $this->getState('filter.state');
        if (is_numeric($published)) {
            $query->where('p.published = ' . (int) $published);
        } elseif ($published === '') {
            $query->where('(p.published IN (0, 1))');
        }
        $theme = $this->getState('filter.theme');
        if (!empty($theme)) {
            $query->where('p.theme = '.(int)$theme);
        }
        $access = $this->getState('filter.access');
        if (!empty($access)) {
            $query->where('p.page_access = '.$db->quote($access));
        }
        $language = $this->getState('filter.language');
        if (!empty($language)) {
            $query->where('p.language = '.$db->quote($language));
        }
        $orderCol = $this->state->get('list.ordering', 'id');
        $orderDirn = $this->state->get('list.direction', 'desc');
        if ($orderCol == 'order_list') {
            $orderDirn = 'ASC';
        }
        $query->order($db->escape('p.' . $orderCol . ' ' . $orderDirn));
        
        return $query;
    }

    public function getItems()
    {
        $store = $this->getStoreId();
        $app = Factory::getApplication();
        if (isset($this->cache[$store])) {
            return $this->cache[$store];
        }
        $query = $this->_getListQuery();
        try {
            $layout = $app->input->get('layout');
            if ($layout == 'modal' || $layout == 'apps') {
                $items = $this->_getList($query, 0, 0);
                $search = $this->getState('filter.search');
                $single = Text::_('PAGES');
                if ($layout == 'apps' && (empty($search) || strpos($single, $search) !== false)) {
                    $obj = new \stdClass();
                    $obj->title = $single;
                    $obj->id = 0;
                    $items[] = $obj;
                    $items = array_reverse($items);
                }
            } else {
                $items = $this->_getList($query, $this->getStart(), $this->getState('list.limit'));
            }
        } catch (\RuntimeException $e) {
            $this->setError($e->getMessage());
            return false;
        }
        $this->cache[$store] = $items;

        return $this->cache[$store];
    }
    
    protected function checkThemes()
    {
        $db = Factory::getDbo();
        $query = $db->getQuery(true);
        $query->select('id, theme');
        $query->from('#__gridbox_pages');
        $db->setQuery($query);
        $pages = $db->loadObjectList();
        $query = $db->getQuery(true);
        $query->select('id')
            ->from('#__template_styles')
            ->where('`client_id` = 0')
            ->where('`template` = ' .$db->Quote('gridbox'))
            ->where('`home` = 1');
        $db->setQuery($query);
        $default = $db->loadResult();
        foreach ($pages as $page) {
            $query = $db->getQuery(true);
            $query->select('id')
                ->from('#__template_styles')
                ->where('`id` = ' .$db->Quote($page->theme));
            $db->setQuery($query);
            $id = $db->loadResult();
            if ($id != $page->theme) {
                $page->theme = $default;
                $db->updateObject('#__gridbox_pages', $page, 'id');
            }
        }
    }
    
    public function getThemes()
    {
        $db = Factory::getDbo();
        $query = $db->getQuery(true);
        $query->select('id, title')
            ->from('#__template_styles')
            ->where('`template` = ' .$db->Quote('gridbox'));
        $db->setQuery($query);
        
        return $db->loadObjectList();
    }
    
    protected function getStoreId($id = '')
    {
        $id .= ':' . $this->getState('filter.search');
        $id .= ':' . $this->getState('filter.state');
        
        return parent::getStoreId($id);
    }
    
    protected function populateState($ordering = null, $direction = null)
    {
        $search = $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search');
        $this->setState('filter.search', $search);
        $published = $this->getUserStateFromRequest($this->context . '.filter.state', 'filter_state', '', 'string');
        $this->setState('filter.state', $published);
        $theme = $this->getUserStateFromRequest($this->context . '.filter.theme', 'theme_filter', '', 'string');
        $this->setState('filter.theme', $theme);
        $access = $this->getUserStateFromRequest($this->context . '.filter.access', 'access_filter', '', 'string');
        $this->setState('filter.access', $access);
        $language = $this->getUserStateFromRequest($this->context . '.filter.language', 'language_filter', '', 'string');
        $this->setState('filter.language', $language);
        parent::populateState('id', 'desc');
    }
}