<?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 Tassos\Framework\Helpers\Widgets\Gallery as GalleryHelper;
use Tassos\Framework\Mimes;
use Tassos\Framework\File;
use Tassos\Framework\Image;
use Joomla\CMS\Factory;

class Slideshow extends Widget
{
	/**
	 * Widget default options
	 *
	 * @var array
	 */
	protected $widget_options = [
		// Slides per view
		'slides_per_view' => [
			'desktop' => 1
		],

		// Space between slides in px
		'space_between_slides' => [
			'desktop' => 10
		],

		// Enable Infinite Loop
		'infinite_loop' => false,

		// Enable Keyboard Control
		'keyboard_control' => false,

		/**
		 * Set the ordering.
		 * 
		 * Available values:
		 * - default
		 * - alphabetical
		 * - reverse_alphabetical
		 * - random
		 */
		'ordering' => 'default',

		/**
		 * The transition effect.
		 * 
		 * Available values:
		 * - slide
		 * - fade
		 * - cube
		 * - coverflow
		 * - flip
		 */
		'transition_effect' => 'slide',

		// Enable Autoplay
		'autoplay' => false,

		// Autoplay delay
		'autoplay_delay' => 3000,

		// Enable autoplay circular progress
		'autoplay_progress' => false,

		// Show thumbnails below the slideshow
		'show_thumbnails' => false,

		// Set whether to show arrows in the thumbnails slider
		'show_thumbnails_arrows' => false,

		/**
		 * Navigation controls.
		 * 
		 * Accepted values:
		 * - arrows
		 * - dots
		 * - arrows_dots
		 */
		'nav_controls' => false,
		
		// Theme color
		'theme_color' => '#007aff',

		// Set whether to display a lightbox
		'lightbox' => false,
		
		// Set the module key to display whenever we are viewing a single item's lightbox, appearing after the image
		'module' => '',

		// Options
		'options' => []
	];

	public function __construct($options = [])
	{
		parent::__construct($options);

		$this->prepare();

		$this->prepareItems();

		$this->setOrdering();

		$this->setCSSVars();
	}

	private function prepare()
	{
		if ($this->options['lightbox'])
		{
			$this->options['css_class'] .= ' lightbox';
		}
		
		$options = [
			'transition_effect' => $this->options['transition_effect'],
			'infinite_loop' => $this->options['infinite_loop'],
			'keyboard_control' => $this->options['keyboard_control'],
			'autoplay' => $this->options['autoplay'],
			'autoplay_delay' => $this->options['autoplay_delay'],
			'autoplay_progress' => $this->options['autoplay_progress'],
			'show_thumbnails' => $this->options['show_thumbnails'],
			'show_thumbnails_arrows' => $this->options['show_thumbnails_arrows'],
			'lightbox' => $this->options['lightbox'],
			'breakpoints' => \Tassos\Framework\Helpers\Responsive::getBreakpointsSettings(),
			'slides_per_view' => $this->options['slides_per_view'],
			'space_between_slides' => $this->getSpaceBetweenSlides(),
			'nav_controls' => $this->options['nav_controls']
		];

		$this->options['options'] = $options;
	}

	private function getSpaceBetweenSlides()
	{
		$space_between_slides = $this->options['space_between_slides'];

		if (is_array($space_between_slides))
		{
			foreach ($space_between_slides as $key => &$value)
			{
				$value = \Tassos\Framework\Helpers\Controls\Control::getCSSValue($value['value']);
			}
		}

		return $space_between_slides;
	}

	/**
	 * Prepares the items.
	 * 
	 * - Sets the thumbnails image dimensions.
	 * - Assures caption property exist.
	 * 
	 * @return  mixed
	 */
	private function prepareItems()
	{
		if (!is_array($this->options['items']) || !count($this->options['items']))
		{
			return;
		}

		$smartTagsInstance = \Tassos\Framework\SmartTags::getInstance();
		
		foreach ($this->options['items'] as $key => &$item)
		{
			// Initialize image atts
			$item['img_atts'] = '';

			// Initializes caption if none given
			if (!isset($item['caption']))
			{
				$item['caption'] = '';
			}

			if (!isset($item['alt']) || empty($item['alt']))
			{
				$item['alt'] = !empty($item['caption']) ? mb_substr($item['caption'], 0, 100) : pathinfo($item['url'], PATHINFO_FILENAME);
			}
			
			// Replace Smart Tags in alt
			$item['alt'] = $smartTagsInstance->replace($item['alt']);
			
			// Ensure a thumbnail is given
			if (!isset($item['thumbnail_url']))
			{
				// If no thumbnail is given, set it to the full image
				$item['thumbnail_url'] = $item['url'];
				continue;
			}

			// If the thumbnail size for this item is given, set the image attributes
			if (isset($item['thumbnail_size']))
			{
				$item['img_atts'] = 'width="' . $item['thumbnail_size']['width'] . '" height="' . $item['thumbnail_size']['height'] . '"';
				continue;
			}
		}
	}
	
	/**
	 * Sets the ordering of the gallery.
	 * 
	 * @return  void
	 */
	private function setOrdering()
	{
		switch ($this->options['ordering']) {
			case 'random':
				shuffle($this->options['items']);
				break;
			case 'alphabetical':
				usort($this->options['items'], [$this, 'compareByThumbnailASC']);
				break;
			case 'reverse_alphabetical':
				usort($this->options['items'], [$this, 'compareByThumbnailDESC']);
				break;
		}
	}

	/**
	 * Compares thumbnail file names in ASC order
	 * 
	 * @param   array  $a
	 * @param   array  $b
	 * 
	 * @return  bool
	 */
	private function compareByThumbnailASC($a, $b)
	{
		return strcmp(basename($a['thumbnail']), basename($b['thumbnail']));
	}

	/**
	 * Compares thumbnail file names in DESC order
	 * 
	 * @param   array  $a
	 * @param   array  $b
	 * 
	 * @return  bool
	 */
	private function compareByThumbnailDESC($a, $b)
	{
		return strcmp(basename($b['thumbnail']), basename($a['thumbnail']));
	}

	/**
	 * Sets the CSS variables.
	 * 
	 * @return  void
	 */
	private function setCSSVars()
	{
		if (!$this->options['load_css_vars'])
		{
			return;
		}
	
		$controls = [
            [
                'property' => '--slideshow-slides-per-view',
                'value' => $this->options['slides_per_view']
            ],
            [
                'property' => '--slideshow-space-between-slides',
                'value' => $this->options['space_between_slides']
            ]
		];

		$selector = '.nrf-widget.tf-slideshow-wrapper.' . $this->options['id'];
		
		$controlsInstance = new \Tassos\Framework\Controls\Controls(null, $selector);

        if (!$controlsCSS = $controlsInstance->generateCSS($controls))
        {
            return;
        }

        Factory::getDocument()->addStyleDeclaration($controlsCSS);
	}
}