<?php
namespace PowerpackElements\Modules\Gallery;

use PowerpackElements\Base\Module_Base;
use PowerpackElements\Classes\PP_Helper;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

class Module extends Module_Base {

	public function __construct() {
		parent::__construct();

		// Gallery module - load more componenet.
		add_action( 'wp', [ $this, 'gallery_get_images' ] );

		add_action( 'elementor/frontend/after_register_styles', [ $this, 'register_styles' ] );
	}

	/**
	 * Module is active or not.
	 *
	 * @since 1.3.3
	 *
	 * @access public
	 *
	 * @return bool true|false.
	 */
	public static function is_active() {
		return true;
	}

	/**
	 * Get Module Name.
	 *
	 * @since 1.3.3
	 *
	 * @access public
	 *
	 * @return string Module name.
	 */
	public function get_name() {
		return 'pp-gallery';
	}

	/**
	 * Get Widgets.
	 *
	 * @since 1.3.3
	 *
	 * @access public
	 *
	 * @return array Widgets.
	 */
	public function get_widgets() {
		return [
			'Image_Gallery',
			'Image_Slider',
		];
	}

	/**
	 * Get Image Caption.
	 *
	 * @since 1.3.3
	 *
	 * @access public
	 *
	 * @return string image caption.
	 */
	public static function get_image_caption( $id, $caption_type = 'caption' ) {

		if ( 'caption' === $caption_type ) {
			return wp_get_attachment_caption( $id );
		}

		if ( 'alt' === $caption_type ) {
			return get_post_meta( $id, '_wp_attachment_image_alt', true );
		}

		// Only the remaining types need the attachment itself.
		if ( 'title' !== $caption_type && 'description' !== $caption_type ) {
			return '';
		}

		$attachment = get_post( $id );

		if ( ! $attachment ) {
			return '';
		}

		return ( 'title' === $caption_type ) ? $attachment->post_title : $attachment->post_content;
	}

	/**
	 * Get gallery images
	 *
	 * Handles the Load More request for the Image Gallery widget. The request is
	 * posted to the current page URL, so it is picked up on the `wp` hook rather
	 * than through admin-ajax.
	 *
	 * The response only ever contains markup the visitor could already see on a
	 * public page, so no nonce is required (one would break under full page
	 * caching). Access is instead constrained by validating the requested
	 * document and the resolved element below.
	 *
	 * @access public
	 */
	public function gallery_get_images() {
		if ( ! isset( $_POST['pp_action'] ) || 'pp_gallery_get_images' !== sanitize_text_field( wp_unslash( $_POST['pp_action'] ) ) ) {
			return;
		}

		if ( empty( $_POST['settings'] ) || ! is_array( $_POST['settings'] ) ) {
			return;
		}

		// Tell WordPress this is an AJAX request.
		if ( ! defined( 'DOING_AJAX' ) ) {
			define( 'DOING_AJAX', true );
		}

		// Only the three keys below are read, and each is sanitized individually.
		$settings = wp_unslash( $_POST['settings'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized

		$gallery_id  = isset( $settings['widget_id'] ) ? sanitize_key( $settings['widget_id'] ) : '';
		$post_id     = isset( $settings['post_id'] ) ? absint( $settings['post_id'] ) : 0;
		$template_id = isset( $settings['template_id'] ) ? absint( $settings['template_id'] ) : 0;

		// The widget lives in the template document when the gallery is used inside a theme builder template.
		if ( $template_id && $template_id !== $post_id ) {
			$post_id = $template_id;
		}

		if ( ! $gallery_id || ! $post_id || ! $this->is_document_readable( $post_id ) ) {
			wp_send_json_error();
		}

		$document = \Elementor\Plugin::$instance->documents->get( $post_id );

		if ( ! $document ) {
			wp_send_json_error();
		}

		$gallery = $this->find_element_recursive( $document->get_elements_data(), $gallery_id );

		// Only an actual image gallery widget may be instantiated and rendered here.
		if ( ! $gallery || ! isset( $gallery['widgetType'] ) || PP_Helper::get_widget_name( 'Image_Gallery' ) !== $gallery['widgetType'] ) {
			wp_send_json_error();
		}

		// Restore default values.
		$widget = \Elementor\Plugin::$instance->elements_manager->create_element_instance( $gallery );

		if ( ! $widget ) {
			wp_send_json_error();
		}

		wp_send_json_success( [ 'items' => $widget->ajax_get_images() ] );
	}

	/**
	 * Check whether a document may be read by the current visitor.
	 *
	 * The document ID arrives from the request, so a publicly visible status is
	 * required before its element data is read. Non public statuses (draft,
	 * private, pending) fall back to a capability check.
	 *
	 * @since 3.0.0
	 * @access protected
	 * @param int $post_id Document ID.
	 * @return bool
	 */
	protected function is_document_readable( $post_id ) {
		$status = get_post_status( $post_id );

		if ( ! $status ) {
			return false;
		}

		$status_object = get_post_status_object( $status );

		if ( $status_object && ! empty( $status_object->public ) ) {
			return true;
		}

		return current_user_can( 'read_post', $post_id );
	}

	/**
	 * Get Widget Setting data.
	 *
	 * @since 1.3.3
	 * @access public
	 * @param array  $elements Element array.
	 * @param string $widget_id Element ID.
	 * @return Boolean True/False.
	 */
	public function find_element_recursive( $elements, $widget_id ) {
		foreach ( $elements as $element ) {
			if ( $widget_id === $element['id'] ) {
				return $element;
			}

			if ( ! empty( $element['elements'] ) ) {
				$element = $this->find_element_recursive( $element['elements'], $widget_id );

				if ( $element ) {
					return $element;
				}
			}
		}

		return false;
	}

	/**
	 * Register styles.
	 *
	 * @return void
	 */
	public function register_styles() {
		wp_register_style(
			'widget-pp-image-gallery',
			$this->get_css_assets_url( 'widget-image-gallery', null, true, true ),
			[],
			POWERPACK_ELEMENTS_VER
		);

		wp_register_style(
			'widget-pp-image-slider',
			$this->get_css_assets_url( 'widget-image-slider', null, true, true ),
			[],
			POWERPACK_ELEMENTS_VER
		);
	}
}
