<?php
/**
 * Plumrocket Inc.
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the End-user License Agreement
 * that is available through the world-wide-web at this URL:
 * http://wiki.plumrocket.net/wiki/EULA
 * If you are unable to obtain it through the world-wide-web, please
 * send an email to support@plumrocket.com so we can send you a copy immediately.
 *
 * @package     Plumrocket Product Filter v3.x.x
 * @copyright   Copyright (c) 2016 Plumrocket Inc. (http://www.plumrocket.com)
 * @license     http://wiki.plumrocket.net/wiki/EULA  End-user License Agreement
 */

namespace Plumrocket\ProductFilter\Plugin\Block\LayeredNavigation\Navigation;

class FilterRenderer
{
    /**
     * @var \Magento\Framework\View\LayoutInterface
     */
    protected $layout;

    /**
     * Path to Render Price Block
     *
     * @var string
     */
    protected $blockPrice = 'Plumrocket\ProductFilter\Block\LayeredNavigation\RenderPrice';

    /**
     * Path to Render Rating Block
     *
     * @var string
     */
    protected $blockRating = 'Plumrocket\ProductFilter\Block\LayeredNavigation\RenderRating';

    /**
     * Active Filters
     * @var array
     */
    protected $_activeFilters = [];

    /**
     * @var array
     */
    protected $optionValues = [];

    /**
     * @var \Plumrocket\ProductFilter\Helper\Data
     */
    private $dataHelper;

    /**
     * @var \Magento\Framework\ObjectManagerInterface
     */
    private $objectManager;

    /**
     * @var \Magento\Framework\Module\Manager
     */
    private $moduleManager;

    /**
     * @param \Magento\Framework\View\LayoutInterface $layout
     * @param \Plumrocket\ProductFilter\Helper\Data $dataHelper
     * @param \Magento\Framework\Module\Manager $moduleManager
     * @param \Magento\Framework\ObjectManagerInterface $objectManager
     */
    public function __construct(
        \Magento\Framework\View\LayoutInterface $layout,
        \Plumrocket\ProductFilter\Helper\Data $dataHelper,
        \Magento\Framework\Module\Manager $moduleManager,
        \Magento\Framework\ObjectManagerInterface $objectManager
    ) {
        $this->layout = $layout;
        $this->dataHelper = $dataHelper;
        $this->moduleManager = $moduleManager;
        $this->objectManager = $objectManager;
    }

    /**
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     * @param \Magento\LayeredNavigation\Block\Navigation\FilterRenderer $subject
     * @param \Closure $proceed
     * @param \Magento\Catalog\Model\Layer\Filter\FilterInterface $filter
     * @return mixed
     * @throws \Magento\Framework\Exception\LocalizedException
     */
    public function aroundRender(
        \Magento\LayeredNavigation\Block\Navigation\FilterRenderer $subject,
        \Closure $proceed,
        \Magento\Catalog\Model\Layer\Filter\FilterInterface $filter
    ) {
        $isAmpRequest = false;

        if ($this->moduleManager->isEnabled('Plumrocket_Amp')) {
            $isAmpRequest = $this->objectManager->get(\Plumrocket\Amp\Helper\Data::class)->isAmpRequest();
        }

        if (!$this->dataHelper->moduleEnabled() || $isAmpRequest) {
            return $proceed($filter);
        }

        $layer = $filter->getLayer();

        foreach ($filter->getItems() as $item) {
            $this->refactorRewritedValue($item);
            $item->setIsActive($this->_isActive($item, $layer));
        }

        $this->optionValues = [];
        $block = null;

        if ($filter instanceof \Magento\Catalog\Model\Layer\Filter\Price
            || $filter instanceof \Magento\CatalogSearch\Model\Layer\Filter\Price
        ) {
            $block = $this->blockPrice;
        } elseif ($filter instanceof \Plumrocket\ProductFilter\Model\Layer\Filter\Rating) {
            $block = $this->blockRating;
        }

        if ($block) {
            return $this->layout
                ->createBlock($block)
                ->setFilter($filter)
                ->toHtml();
        }

        return $proceed($filter);
    }

    /**
     * Is filter active
     * @param  object $item
     * @param object  $layer
     * @return boolean
     */
    protected function _isActive($item, $layer)
    {
        $value = (string) $item->getValue();
        $aditionalValue = str_replace(' ', '_', strtolower($value));
        if ($value == '0') {
            $value = 'no';
        }
        $attributeCode = $item->getData('filter')->getData('pf_attribute_code');
        $activeFilters = $this->_getActiveFilters($layer);

        return $item->getIsActive()
            || (isset($activeFilters[$attributeCode])
                && (in_array($value, $activeFilters[$attributeCode])
                    || in_array($aditionalValue, $activeFilters[$attributeCode]))
            );
    }

    /**
     * Retrieve active filter
     * @param object $layer
     * @return array
     */
    protected function _getActiveFilters($layer)
    {
        if (! $this->_activeFilters) {
            if (! empty($layer->getState()->getFilters())) {
                foreach ($layer->getState()->getFilters() as $filter) {
                    $attributeCode = $filter->getData('filter')->getData('pf_attribute_code');
                    $value = $filter->getValue();

                    if (!is_array($value)) {
                        $value = strtolower($value);
                    }

                    $this->_activeFilters[$attributeCode][] = $value;
                }
            }
        }

        return $this->_activeFilters;
    }

    /**
     * @param $option
     * @return $this
     */
    private function refactorRewritedValue($option)
    {
        $value = $option->getRewritedValue();

        if (isset($this->optionValues[$value])) {
            $value .= '_' . $option->getValue();
            $option->setRewritedValue($value);
        }

        $this->optionValues[$value] = $value;

        return $this;
    }
}
