<?php
/**
 * @package    pixelcms_articles
 *
 * @author     christophf <your@email.com>
 * @copyright  A copyright
 * @license    GNU General Public License version 2 or later; see LICENSE.txt
 * @link       http://your.url.com
 */


defined('_JEXEC') or die;

require_once 'BaseModel.php';

/**
 * Pixelcms_articles model.
 *
 * @package  pixelcms_articles
 * @since    1.0
 */
class Pixelcms_articlesModelPixelcms_articles extends BaseModel
{
    protected $api_endpoint;
    protected $module;
    protected $articleId;
    protected $category_id;
    protected $cms_url;
    protected $alias;
    protected $filter;
    protected $api_version;
	protected $state;
	protected $limit;
	protected $page;
	protected $perPage;

	protected $defaults = [
		'cut_images' => 1,
		'image_fallback' => 1,
        'disable_title_image' => 0,
        'show_date' => 'before',
        'intro_length' => 200,
	];

    public function __construct(array $config = array())
    {
        parent::__construct($config);

        /** @var extendedRegistry $params - Settings for current Menu Item */
        $params = $this->getState('params');

        $this->limit = $params->getInt('limit', 5);
        $this->category_id = $params->getInt('pixelcms_category_id');
        $this->articleId = $params->get('articleId', null);
        $this->filter = $params->get('pixelcms_filter', 'active');

        if (!$params->get('is_module', false)) {
            $this->page = $params->getInt('page', 1);
            $this->perPage = $params->getInt('perPage', 10);
        }

        $this->alias = $params->get('pixel_cms_alias');
        $this->cms_url = $params->get('pixel_cms_url');
        $this->api_version = $params->get('pixel_cms_version');
        $this->api_endpoint = 'articles';
        $this->module = "pixelcms_articles";
    }

    private function filterArticles($articles)
    {
        // Already Filtered
        if (is_object($articles)) {
            if ($articles->id !== (int) $this->articleId) return [];
            return $articles;
        }

        if ($this->articleId && is_array($articles)) {
            if (is_array($this->articleId)) {
                if (in_array("", $this->articleId)) return $articles;
                $articles =  array_filter($articles, function ($article) {
                    return in_array($article->id, $this->articleId);
                });
            } else {
                $articles = array_reduce($articles, function ($carry, $article) {
                    if ($article->id == $this->articleId) {
                        $carry = $article;
                    }
                    return $carry;
                });
            }
        }

        return $articles;
    }

    private function applyFilter($articles)
    {
        $singleArticle = !is_array($articles);

        if ($singleArticle) {
            $articles = [$articles];
        }

        $articles = array_filter($articles, function($article) {
            if ($this->filter === 'active') {
                return $article->published && $article->active;
            } else if ($this->filter === 'promoted') {
                return $article->published && $article->active && $article->promoted;
            }
            return true;
        });

        return ($singleArticle) ? $articles[0] : $articles;
    }

    public function getArticle()
    {
        $articleData = $this->getCachedArticles();
        if (isset($articleData->data)) {
            $articleData->data = $this->applyFilter($this->filterArticles($articleData->data));
        } else {
            $articleData = $this->applyFilter($this->filterArticles($articleData));
        }

        return $articleData;
    }

    public function getCategory()
    {
        $data = $this->getCachedCategories();
        if ($this->category_id) {
            return array_reduce($data, function ($carry, $category) {
                if ($category->id === $this->category_id) {
                    $carry = $category;
                }
                return $carry;
            });
        }
        return $data;
    }

    private function getCachedArticles()
    {
        $categoryIds = $this->category_id;
        $articlesIds = (is_array($this->articleId)) ? implode(',', $this->articleId) : $this->articleId;
        $cacheKey = "$this->api_endpoint:l:$this->limit;c:$categoryIds;f:$this->filter";

        if ($this->page) {
            $cacheKey .= "p:$this->page";
        }

        // Category list, maybe contains our article
        $articleData = $this->cache->get($cacheKey, $this->module);

        if ($this->articleId) {
            $decoded = json_decode($articleData);
            $articles = isset($decoded->data) ? $decoded->data : $decoded;
            $cachedIds = (is_array($articles)) ? array_column($articles, 'id') : [];
            if (empty($articles) || !array_reduce(
                    is_array($articlesIds) ? $articlesIds : [$articlesIds],
                    function ($carry, $value) use ($cachedIds) {
                        return $carry && in_array($value, $cachedIds);
                    },
                    true
                )) {
                $cacheKey = "$this->api_endpoint:id:$articlesIds";
                $articleData = $this->cache->get($cacheKey, $this->module);
            }
        }

        if (empty($articleData)) {
            $articleData = $this->getData();
            $this->cache->store($articleData, $cacheKey, $this->module);
        }

        return json_decode($articleData);
    }

    public function getCachedCategories()
    {
        $categories = $this->cache->get('categories', $this->module);

        if (empty($categories)) {
            $categories = $this->getCategories();
            $this->cache->store($categories, 'categories', $this->module);
        }

        return json_decode($categories);
    }

    private function getData()
    {
        $parameters = [];

        if ($this->category_id) {
            $parameters['category'] = $this->category_id;
        }

	    if ($this->limit > 0 && !is_array($this->articleId)) {
		    $parameters['limit'] = $this->limit;
	    }

	    if ($this->page) {
	        if ($this->perPage > 0) {
                $parameters['page'] = $this->page;
                $parameters['perPage'] = $this->perPage;
            }
            unset($parameters['limit']);
        }

        $url = $this->cms_url . '/api/' . $this->api_version . '/' . "$this->api_endpoint/$this->filter";

        if ($this->filter === 'all') {
            $url = $this->cms_url . '/api/' . $this->api_version . '/' . "$this->api_endpoint";
        }

        if ($this->articleId) {
            $parameters = [];
            $ids = (is_array($this->articleId)) ? implode(',', $this->articleId) : $this->articleId;
            $url = $this->cms_url . '/api/' . $this->api_version . '/' . "$this->api_endpoint/$ids";
        }

        return $this->cURL($url, $parameters);
    }

    private function getCategories()
    {
        $parameters = [];

        $url = $this->cms_url . '/api/' . $this->api_version . '/' . "categories";

        return $this->cURL($url, $parameters);
    }
}
