<?php
/**
 * @category Mageants HyvaSimpleConfigurable
 * @package Mageants_HyvaSimpleConfigurable
 * @copyright Copyright (c) 2023 Mageants
 * @author Mageants Team <info@mageants.com>
 */
namespace Mageants\HyvaSimpleConfigurable\Block\Product\Renderer;

use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Catalog\Block\Product\Context;
use Magento\Catalog\Helper\Product as CatalogProduct;
use Magento\Catalog\Model\Product;
use Magento\ConfigurableProduct\Helper\Data;
use Magento\ConfigurableProduct\Model\ConfigurableAttributeData;
use Magento\Customer\Helper\Session\CurrentCustomer;
use Magento\Framework\App\ObjectManager;
use Magento\Framework\Json\EncoderInterface;
use Magento\Framework\Pricing\PriceCurrencyInterface;
use Magento\Framework\Stdlib\ArrayUtils;
use Magento\Store\Model\ScopeInterface;
use Magento\Swatches\Helper\Data as SwatchData;
use Magento\Swatches\Helper\Media;
use Magento\Swatches\Model\Swatch;
use Magento\Swatches\Model\SwatchAttributesProvider;
use Magento\Framework\View\DesignInterface;
use Mageants\SimpleConfigurable\Block\Product\Renderer\Configurable as MageantsConfigurable;
use Magento\Catalog\Model\Product\Image\UrlBuilder;
use Mageants\SimpleConfigurable\Helper\Data as SimpleConfigurable;
use Magento\Framework\View\LayoutFactory;
use Magento\Catalog\Helper\Output;
use Magento\Catalog\Model\ProductRepository;
use Magento\Eav\Model\Config;
use Magento\Catalog\Model\ProductFactory;

/**
 * Swatch renderer block
 *
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 */
class Configurable extends MageantsConfigurable
{
    /**
     * Path to template file with Swatch renderer.
     */
    public const MAGEANTS_WATCH_RENDERER_TEMPLATE = 'Mageants_SimpleConfigurable::product/view/renderer.phtml';

    /**
     * Path to default template file with standard Configurable renderer.
     */
    public const MAGEANTS_CONFIGURABLE_RENDERER_TEMPLATE =
        'Mageants_SimpleConfigurable::product/view/type/options/configurable.phtml';

    /**
     * Path to template file with Swatch renderer.
     */
    public const SWATCH_RENDERER_TEMPLATE = 'Magento_Swatches::product/view/renderer.phtml';

    /**
     * Path to default template file with standard Configurable renderer.
     */
    public const CONFIGURABLE_RENDERER_TEMPLATE =
    'Magento_ConfigurableProduct::product/view/type/options/configurable.phtml';

    /**
     * @var \Magento\Framework\View\DesignInterface
     */
    protected $theme;

    /**
     * Constructor Dependencies
     *
     * @param Context                       $context
     * @param ArrayUtils                    $arrayUtils
     * @param EncoderInterface              $jsonEncoder
     * @param Data                          $helper
     * @param CatalogProduct                $catalogProduct
     * @param CurrentCustomer               $currentCustomer
     * @param PriceCurrencyInterface        $priceCurrency
     * @param ConfigurableAttributeData     $configurableAttributeData
     * @param SwatchData                    $swatchHelper
     * @param Media                         $swatchMediaHelper
     * @param SimpleConfigurable            $simpleConfigurableHelper
     * @param SwatchAttributesProvider|null $swatchAttributesProvider
     * @param LayoutFactory                 $layoutFactory
     * @param Output                        $output
     * @param Product                       $productObj
     * @param DesignInterface               $theme
     * @param UrlBuilder|null               $imageUrlBuilder
     * @param array                         $data
     */
    public function __construct(
        Context $context,
        ArrayUtils $arrayUtils,
        EncoderInterface $jsonEncoder,
        Data $helper,
        CatalogProduct $catalogProduct,
        CurrentCustomer $currentCustomer,
        PriceCurrencyInterface $priceCurrency,
        ConfigurableAttributeData $configurableAttributeData,
        SwatchData $swatchHelper,
        Media $swatchMediaHelper,
        SimpleConfigurable $simpleConfigurableHelper,
        LayoutFactory $layoutFactory,
        Output $output,
        ProductRepository $productRepository,
        Config $config,
        Product $productObj,
        ProductFactory $productFactory,
        DesignInterface $theme,
        ?UrlBuilder $imageUrlBuilder = null,
        ?SwatchAttributesProvider $swatchAttributesProvider = null,
        array $data = []
    ) {

        parent::__construct(
            $context,
            $arrayUtils,
            $jsonEncoder,
            $helper,
            $catalogProduct,
            $currentCustomer,
            $priceCurrency,
            $configurableAttributeData,
            $swatchHelper,
            $swatchMediaHelper,
            $simpleConfigurableHelper,
            $layoutFactory,
            $output,
            $productObj,
            $productRepository,
            $config,
            $productFactory,
            $swatchAttributesProvider,
            $imageUrlBuilder,
            $data
        );

        $this->theme = $theme;
    }

     /**
      * GetRendererTemplate
      *
      * @return string
      */
    public function getRendererTemplate()
    {
        if (!$this->isHyva()) {
            return $this->isProductHasSwatchAttribute() ?
            self::MAGEANTS_WATCH_RENDERER_TEMPLATE : self::MAGEANTS_CONFIGURABLE_RENDERER_TEMPLATE;

        } else {

            return $this->isProductHasSwatchAttribute() ?
            self::SWATCH_RENDERER_TEMPLATE : self::CONFIGURABLE_RENDERER_TEMPLATE;
        }
    }

    /**
     * Returns true if the current theme is a Hyva theme,a descendant of Hyva/reset (or any Hyva namespaced theme)
     *
     * @return bool
     */
    public function isHyva(): bool
    {
        $theme = $this->theme->getDesignTheme();
        while ($theme) {
            if (strpos($theme->getCode(), 'Hyva/') === 0) {
                return true;
            }
            $theme = $theme->getParentTheme();
        }
        return false;
    }

    /**
     * Get Swatch config data
     *
     * @return string
     */
    public function getJsonSwatchConfig()
    {
        if (!$this->isHyva()) {
            return parent::getJsonSwatchConfig();

        } else {

            $attributesData = $this->getSwatchAttributesData();
            $allOptionIds = $this->getConfigurableOptionsIds($attributesData);
            $swatchesData = $this->swatchHelper->getSwatchesByOptionsId($allOptionIds);

            $config = [];
            foreach ($attributesData as $attributeId => $attributeDataArray) {
                if (isset($attributeDataArray['options'])) {
                    $config[$attributeId] = $this->addSwatchDataForAttribute(
                        $attributeDataArray['options'],
                        $swatchesData,
                        $attributeDataArray
                    );
                }
                if (isset($attributeDataArray['additional_data'])) {
                    $config[$attributeId]['additional_data'] = $attributeDataArray['additional_data'];
                }
            }

            return $this->jsonEncoder->encode($config);
        }
    }
}
