<?php

/**
 * @author          Tassos Marinos <info@tassos.gr>
 * @link            https://www.tassos.gr
 * @copyright       Copyright © 2024 Tassos All Rights Reserved
 * @license         GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
 */

namespace Tassos\Framework\Widgets;

defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\Registry\Registry;

class FAQ extends Widget
{
	/**
	 * Widget default options
	 *
	 * @var array
	 */
	protected $widget_options = [
		/**
		 * FAQ Settings
		 */

		/**
		 * The questions and answers.
		 * 
		 * Format:
		 * 
		 * [
		 *  	[
		 * 			'question' => 'Question 1',
		 * 			'answer' => 'Answer 1'
		 * 		],
		 *  	[
		 * 			'question' => 'Question 2',
		 * 			'answer' => 'Answer 2'
		 * 		],
		 * ]
		 */ 
		'value' => '',

		/**
		 * Requires "show_toggle_icon" to be enabled to work.
		 * 
		 * Define the initial state of the FAQ.
		 * 
		 * Available values:
		 * 
		 * - first-open: Open the first question
		 * - all-open: Opens all questions
		 * - all-closed: Closes all questions
		 */
		'initial_state' => 'first-open',

		// Set whether to have one question open at a time
		'keep_one_question_open' => true,

		// Set the columns.
		'columns' => 1,

		// Set the gap between the items.
		'item_gap' => 16,

		// Set the gap between the columns.
		'column_gap' => 16,

		// Set whether to display a separator between items
		'separator' => false,

		// Set the separator color
		'separator_color' => '',

		/**
		 * Item Settings
		 */
		// Each item background color.
		'item_background_color' => null,

		// Each item border radius.
		'item_border_radius' => null,

		// Each item padding.
		'item_padding' => null,

		/**
		 * Question
		 */
		// Question font size
		'question_font_size' => null,

		// Each question text color.
		'question_text_color' => null,

		/**
		 * Answer
		 */
		// Answer font size
		'answer_font_size' => null,

		// Each answer text color.
		'answer_text_color' => null,

		/**
		 * Icon Settings
		 */
		/**
		 * Whether to show an icon that can toggle the open/close state of the answer.
		 * 
		 * If disabled, all answers will appear by default.
		 * If enabled, all answers will be hidden by default.
		 */
		'show_toggle_icon' => false,

		/**
		 * Set the icon that will be used.
		 * 
		 * Available values:
		 * - arrow
		 * - plus_minus
		 * - circle_arrow
		 * - circle_plus_minus
		 */
		'icon' => 'arrow',

		/**
		 * Set the icon position.
		 * 
		 * Available values:
		 * 
		 * - right
		 * - left
		 */
		'icon_position' => 'right',

		/**
		 * FAQ Schema
		 */
		// Set whether to generate the FAQ Schema on the page.
		'generate_faq' => false,

		// Custom Item CSS Classes
		'item_css_class' => ''
	];

	/**
	 * Class constructor
	 *
	 * @param array $options
	 */
	public function __construct($options = [])
	{
		parent::__construct($options);

		$this->prepare();
	}

	/**
	 * Prepares the FAQ.
	 * 
	 * @return  void
	 */
	private function prepare()
	{
		if ($this->options['show_toggle_icon'])
		{
			$this->options['show_toggle_icon'] = true;
			$this->options['css_class'] .= ' has-icons';
			$this->options['css_class'] .= ' position-icon-' . $this->options['icon_position'];
			$this->options['css_class'] .= ' has-icon-' . $this->options['icon'];
		}

		if (!empty($this->options['item_background_color']) && $this->options['item_background_color'] !== 'none')
		{
			$this->options['css_class'] .= ' has-item-bg-color';
		}

		if ($this->options['separator'])
		{
			$this->options['css_class'] .= ' has-separator';
		}

		$this->options['css_class'] .= ' ' . $this->options['initial_state'];

		if ($this->options['keep_one_question_open'])
		{
			$this->options['css_class'] .= ' keep-one-question-open';
		}

		if ((int) $this->options['columns'] > 1)
		{
			$this->options['css_class'] .= ' has-columns';
		}

		$this->generateFAQ();
		
		if ($this->options['load_css_vars'])
		{
			$this->options['custom_css'] = $this->getWidgetCSS();
		}
	}

	private function generateFAQ()
	{
		// Ensure "generate_faq" is enabled
		if (!$this->options['generate_faq'])
		{
			return;
		}
		
		// Ensure we have questions and answers
		if (!is_array($this->options['value']) && !count($this->options['value']))
		{
			return;
		}

		// Abort if FAQ cannot be compiled
		if (!$faq = $this->getFAQ())
		{
			return;
		}

		// This is the new way to add structured data on the page
		if (class_exists('\GSD\Schemas\SchemaManager'))
		{
			$schemaManager = \GSD\Schemas\SchemaManager::getInstance();
			$schemaManager->addSchema($faq);
			return;
		}

		// The following way adding structured data is deprecated and will be removed in future versions
		Factory::getApplication()->registerEvent('onGSDBeforeRender', function(&$data) use ($faq)
		{
			try
			{
				// get the data
				$tmpData = $data;
				$tmpData = $data->getArgument('0');

				// Get the JSON/LD code of the FAQ
				$json = new \GSD\Json($faq->get());
				$faq = $json->generate();

				// Append the FAQ Schema
				$tmpData[] = $faq;

				// Ensure unique FAQ
				$tmpData = array_unique($tmpData);
				
				// Set back the new value to $data object
				$data->setArgument(0, $tmpData);
			} catch (\Throwable $th)
			{
				$this->throwError($th->getMessage());
			}
		});
	}

	/**
	 * Returns the FAQ JSON/LD code.
	 * 
	 * @return  string
	 */
	private function getFAQ()
	{
		$autoload_file = JPATH_ADMINISTRATOR . '/components/com_gsd/autoload.php';
		if (!file_exists($autoload_file))
		{
			return;
		}

		require_once $autoload_file;
		
		// Prepare the FAQ
		$payload = [
			'mode' => 'manual',
			'faq_repeater_fields' => json_decode(json_encode($this->options['value']))
		];
		$payload = new Registry($payload);
		$faq = new \GSD\Schemas\Schemas\FAQ($payload);

		return $faq;
	}

	/**
	 * Returns the CSS for the widget.
	 * 
	 * @param   array  $exclude_breakpoints   Define breakpoints to exclude their CSS
	 * 
	 * @return  string
	 */
	public function getWidgetCSS($exclude_breakpoints = [])
	{
		$controls = [
			// CSS Variables
            [
                'property' => '--item-background-color',
                'value' => $this->options['item_background_color']
			],
            [
                'property' => '--question-text-color',
                'value' => $this->options['question_text_color']
			],
            [
                'property' => '--answer-text-color',
                'value' => $this->options['answer_text_color']
			],
            [
                'property' => '--separator-color',
                'value' => $this->options['separator_color']
			],

			// CSS
            [
                'property' => '--item-padding',
				'type' => 'Spacing',
                'value' => $this->options['item_padding'],
				'unit' => 'px'
			],
            [
                'property' => '--item-gap',
                'value' => $this->options['item_gap'],
				'unit' => 'px'
			],
            [
                'property' => '--column-gap',
                'value' => $this->options['column_gap'],
				'unit' => 'px'
			],
            [
                'property' => '--item-border-radius',
				'type' => 'Spacing',
                'value' => $this->options['item_border_radius'],
				'unit' => 'px'
			],
            [
                'property' => '--question-font-size',
                'value' => $this->options['question_font_size'],
				'unit' => 'px'
			],
            [
                'property' => '--answer-font-size',
                'value' => $this->options['answer_font_size'],
				'unit' => 'px'
			],
		];

		$selector = '.tf-faq-widget.' . $this->options['id'];
		
		$controlsInstance = new \Tassos\Framework\Controls\Controls(null, $selector, $exclude_breakpoints);
        
		if (!$controlsCSS = $controlsInstance->generateCSS($controls))
		{
			return;
		}

		return $controlsCSS;
	}

	/**
	 * Returns all CSS files.
	 * 
	 * @return  array
	 */
	public static function getCSS()
	{
		return [
			'plg_system_nrframework/widgets/faq.css'
		];
	}

	/**
	 * Returns all JS files.
	 * 
	 * @param   string  $theme
	 * 
	 * @return  array
	 */
	public static function getJS()
	{
		return [
			'plg_system_nrframework/widgets/faq.js'
		];
	}
}