<?php

/**
 * @package         Google Structured Data
 * @version         6.1.2 Pro
 *
 * @author          Tassos Marinos <info@tassos.gr>
 * @link            http://www.tassos.gr
 * @copyright       Copyright © 2021 Tassos Marinos All Rights Reserved
 * @license         GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
 */

defined('_JEXEC') or die('Restricted access');

use GSD\PluginBaseProduct;
use NRFramework\Cache;
use NRFramework\Extension;
use GSD\MappingOptions;

/**
 *  J2Store Google Structured Data Plugin
 * 
 *  Note: If a J2Store Product is assigned to a Single Article menu type the plugin doesn't recognize the product.
 *  https://www.j2store.org/component/kunena/2-general-questions/5487-single-product-from-menu-item.html
 */
class plgGSDJ2Store extends PluginBaseProduct
{
	/**
	 *  Get product tag's data
	 *
	 *  @return  array
	 */
	public function viewProductTags()
	{
		return $this->viewProducts();
	}
		
	/**
	 *  Get products's data
	 *
	 *  @return  array
	 */
	public function viewProducts()
	{
		// Make sure J2Store is loaded
		if (!class_exists('J2Product'))
		{
			return;
		}

		// Make sure we have a valid ID
		if (!$id = $this->getThingID())
		{
			return;
		}

		// Get product information
		$item = J2Product::getInstance()->setId($id)->getProduct();

		if (!is_object($item) || !isset($item->source))
		{
			return;
		}

		// Array data
		$payload = [
			'id'   		   => $item->source->id,
			'alias'        => $item->source->alias,
			'headline'     => $item->product_name,
			'description'  => empty($item->product_short_desc) ? $item->product_long_desc : $item->product_short_desc,
			'introtext'    => $item->product_short_desc,
			'fulltext'     => $item->product_long_desc,
			'image'        => $item->main_image,
            'imagetext'	   => \GSD\Helper::getFirstImageFromString($item->product_short_desc . $item->product_long_desc),
			'offerPrice'   => $item->pricing->price,
			'currency'	   => J2Currency::getInstance()->getCode(),
			'brand'	       => $item->manufacturer,
			'sku'		   => $item->variant->sku,
			'created_by'   => $item->source->created_by,
			'created'      => $item->source->created,
			'modified'     => $item->source->modified,
			'publish_up'   => $item->source->publish_up,
			'publish_down' => $item->source->publish_down,
			'ratingValue'  => isset($item->source->rating) ? $item->source->rating : null,
			'reviewCount'  => isset($item->source->rating_count) ? $item->source->ratring_count : null,
			'metakey'	   => $item->source->metakey,
			'metadesc'	   => $item->source->metadesc
		];

		$this->attachCustomFields($item, $payload);
		
		return $payload;
	}

	/**
	 * Append Custom Fields to payload
	 *
	 * @param	object	$article
	 * @param	array	$payload
	 * @param   string 	$prefix
	 *
	 * @return	void
	 */
	private function attachCustomFields($article, &$payload, $prefix = 'cf.')
	{
		$fields = $this->getCustomFields($article);

		if (!is_array($fields) || count($fields) == 0)
		{
			return;
		}

		foreach ($fields as $key => $field)
		{
			$field_path = $prefix . strtolower($field->name);
			$value = $field->value;

			if ($field->rawvalue && $field->value != $field->rawvalue)
			{
				$value = $field->rawvalue;
			}

			if ($field->type === 'media')
			{
				$value_decoded = json_decode($value, true);
				$value = $value_decoded && isset($value_decoded['imagefile']) ? $value_decoded['imagefile'] : $value;
			}

			if ($field->type === 'acfupload')
			{
				$value = is_string($value) && json_decode($value, true) ? json_decode($value, true) : $value;
				if (is_array($value))
				{
					$value = array_values($value);
				}
				$value = isset($value[0]['value']) ? $value[0]['value'] : $value;
			}
			else if ($field->type === 'acfgallery')
			{
				$value = is_string($value) && json_decode($value, true) ? json_decode($value, true) : $value;
				$value = isset($value['items'][0]['image']) ? $value['items'][0]['image'] : $value;
			}

			$payload[$field_path] = is_array($value) ? @implode(', ', $value) : $value;
		}
	}


	/**
	 * The MapOptions Backend Event. Triggered by the mappingoptions fields to help each integration add its own map options.
	 *  
	 * @param	string	$plugin
	 * @param	array	$options
	 *
	 * @return	void
	 */
    public function onMapOptions($plugin, &$options)
    {
		if ($plugin != $this->_name)
        {
			return;
		}

		// Add Custom Fields
		if (!$custom_fields = $this->getCustomFields())
		{
			return;
		}

		$custom_fields_options = [];
	
		foreach ($custom_fields as $key => $field)
		{
			$custom_fields_options[$field->name] = $field->title;
		}

		MappingOptions::add($options, $custom_fields_options);
    }

	/**
	 * Load Joomla Articles Custom Fields
	 *
	 * @param  mixed $article
	 *
	 * @return void
	 */
	private function getCustomFields($article = null)
	{
		$hash = md5($this->_name . 'cf');

		if (Cache::has($hash))
		{
			return Cache::get($hash);
		}

		JLoader::register('FieldsHelper', JPATH_ADMINISTRATOR . '/components/com_fields/helpers/fields.php');

		if (!class_exists('FieldsHelper'))
		{
			return;
		}

		if ($article->product_source_id)
		{
			$article->id = $article->product_source_id;
		}

		$fields = FieldsHelper::getFields('com_content.article', $article, true);

		return Cache::set($hash, $fields);
	}
	
	/**
	 * Remove J2Store Product microdata from all page.
	 *
	 * @return void
	 */
	public function onAfterRender()
	{
        // Make sure we are on the right context
        if ($this->app->isClient('administrator') || !$this->params->get('removemicrodata', true))
		{
            return;
        }

        \GSD\SchemaCleaner::remove('Product', false, true);
	}
}
