<?php

/**
 * Podcasts Widget.
 *
 * @link    https://aiopodcasting.com
 * @since   1.0.0
 *
 * @package AiO_Podcast_Studio
 */

// Exit if accessed directly
if ( ! defined( 'WPINC' ) ) {
	die;
}

/**
 * AIOPOD_Widget_Podcasts class.
 *
 * @since 1.0.0
 */
class AIOPOD_Widget_Podcasts extends WP_Widget {
	
	/**
     * Unique identifier for the widget.
     *
     * @since  1.0.0
	 * @access protected
     * @var    string
     */
    protected $widget_slug;
	
	/**
     * Widget fields.
     *
     * @since  1.0.0
	 * @access private
     * @var    array
     */
	private $fields;
	
	/**
     * Default settings.
     *
     * @since  1.0.0
	 * @access private
     * @var    array
     */
    private $defaults;
	
	/**
	 * Get things started.
	 *
	 * @since 1.0.0
	 */
	public function __construct() {		
		$this->widget_slug = 'aiopod-widget-podcasts';		
		$this->fields      = $this->get_fields();
		$this->defaults    = $this->get_defaults();
		
		parent::__construct(
			$this->widget_slug,
			__( 'AIOPOD - Podcasts', 'aio-podcast-studio' ),
			array(
				'classname'   => $this->widget_slug,
				'description' => __( 'Display a list of your podcasts.', 'aio-podcast-studio' )
			)
		);		
	}

	/**
	 * Outputs the content of the widget.
	 *
	 * @since 1.0.0
	 * @param array	$args	  The array of form elements.
	 * @param array $instance The current instance of the widget.
	 */
	public function widget( $args, $instance ) {
		// Merge incoming $instance array with $defaults
		if ( count( $instance ) ) {
			$attributes = array_merge( $this->defaults, $instance );
		} else {
			$attributes = $this->defaults;
		}

		$attributes = $this->resolve_attributes( $attributes );	
		
		$widget_args = $args;	

		// Enqueue dependencies
		wp_enqueue_style( AIOPOD_PLUGIN_SLUG . '-public' );
		wp_enqueue_script( AIOPOD_PLUGIN_SLUG . '-public' );
		
		// Define the query
		$args = array(				
			'post_type'      => 'aiopod_podcasts',
			'posts_per_page' => ! empty( $attributes['limit'] ) ? (int) $attributes['limit'] : 100,
			'post_status'    => array( 'publish' )
		);

		if ( 'none' !== $attributes['pagination'] ) { // Pagination
			$args['paged'] = (int) $attributes['paged'];
		}

		// Taxonomy Parameters
		$tax_queries = array();

		if ( ! empty( $attributes['categories'] ) ) { // Categories
			$categories = is_array( $attributes['categories'] ) ? array_map( 'intval', $attributes['categories'] ) : array_map( 'intval', explode( ',', $attributes['categories'] ) );
			$categories = array_filter( $categories );

			if ( ! empty( $categories ) ) {
				$tax_queries[] = array(
					'taxonomy'         => 'aiopod_categories',
					'field'            => 'term_id',
					'terms'            => $categories,
					'include_children' => false
				);
			}
		}

		if ( ! empty( $attributes['participants'] ) ) { // Participants
			$participants = array_map( 'intval', ( is_array( $attributes['participants'] ) ? $attributes['participants'] : explode( ',', $attributes['participants'] ) ) );
			$participants = array_filter( $participants );

			if ( ! empty( $participants ) ) {
				$tax_queries[] = array(
					'taxonomy'         => 'aiopod_participants',
					'field'            => 'term_id',
					'terms'            => $participants,
					'include_children' => false
				);
			}
		}
		
		$count_tax_queries = count( $tax_queries );
		if ( $count_tax_queries ) {
			$args['tax_query'] = ( $count_tax_queries > 1 ) ? array_merge( array( 'relation' => 'AND' ), $tax_queries ) : $tax_queries;
		}

		// Order & Orderby Parameters
		$orderby = sanitize_text_field( $attributes['orderby'] );
		$order   = sanitize_text_field( $attributes['order'] );

		switch ( $orderby ) {
			case 'popularity':
				$args['orderby']  = 'meta_value_num';
				$args['meta_key'] = 'total_downloads_plays';
				$args['order']    = $order;
				break;

			case 'downloads':
				$args['orderby']  = 'meta_value_num';
				$args['meta_key'] = 'total_downloads';
				$args['order']    = $order;
				break;

			case 'plays':
				$args['orderby']  = 'meta_value_num';
				$args['meta_key'] = 'total_plays';
				$args['order']    = $order;
				break;

			case 'rand':
				$seed = aiopod_get_orderby_rand_seed();
				$args['orderby'] = 'RAND(' . $seed . ')';
				break;

			default:
				$args['orderby'] = $orderby;
				$args['order']   = $order;
		}
	
		$args = apply_filters( 'aiopod_query_args', $args, $attributes );
		$aiopod_query = new WP_Query( $args );
		
		// Process output
		echo wp_kses_post( $widget_args['before_widget'] );

		if ( ! empty( $instance['title'] ) ) {
			echo wp_kses_post( $widget_args['before_title'] . apply_filters( 'widget_title', $instance['title'] ) . $widget_args['after_title'] );
		}
		
		if ( $aiopod_query->have_posts() ) {		
			if ( ( is_front_page() && is_home() ) || 'none' === $attributes['pagination'] ) {
				$attributes['count'] = $aiopod_query->post_count;
			} else {
				$attributes['count'] = $aiopod_query->found_posts;
			}

			if ( 'none' !== $attributes['pagination'] ) {
				$attributes['max_num_pages'] = $aiopod_query->max_num_pages;
			}
		}

		include apply_filters( 'aiopod_load_template', AIOPOD_PLUGIN_DIR . 'public/templates/podcasts/podcasts-grid.php', $attributes );

		echo wp_kses_post( $widget_args['after_widget'] );
	}
	
	/**
	 * Processes the widget's options to be saved.
	 *
	 * @since 1.0.0
	 * @param array	$new_instance The new instance of values to be generated via the update.
	 * @param array $old_instance The previous instance of values before the update.
	 */
	public function update( $new_instance, $old_instance ) {
		$instance = $old_instance;		

		$instance['title'] = isset( $new_instance['title'] ) ? strip_tags( $new_instance['title'] ) : '';
		
		foreach ( $this->fields['podcasts']['sections'] as $section ) {
			foreach ( $section['fields'] as $field ) {
				$field_name = $field['name'];

				if ( 'number' === $field['type'] ) {
					if ( ! empty( $new_instance[ $field_name ] ) ) {
						$instance[ $field_name ] = ( false === strpos( $new_instance[ $field_name ], '.' ) ) ? (int) $new_instance[ $field_name ] : (float) $new_instance[ $field_name ];
					} else {
						$instance[ $field_name ] = 0;
					}
				} elseif ( 'url' === $field['type'] ) {
					$instance[ $field_name ] = ! empty( $new_instance[ $field_name ] ) ? aiopod_sanitize_url( $new_instance[ $field_name ] ) : '';
				} elseif ( 'checkbox' === $field['type'] ) {
					$instance[ $field_name ] = isset( $new_instance[ $field_name ] ) ? (int) $new_instance[ $field_name ] : 0;
				} elseif ( 'categories' === $field['type'] ) {
					$instance['categories'] = isset( $new_instance['categories'] ) ? array_map( 'intval', $new_instance['categories'] ) : array();
				} elseif ( 'participants' === $field['type'] ) {
					$instance['participants'] = isset( $new_instance['participants'] ) ? array_map( 'intval', $new_instance['participants'] ) : array();
				} else {
					$instance[ $field_name ] = ! empty( $new_instance[ $field_name ] ) ? sanitize_text_field( $new_instance[ $field_name ] ) : '';
				}
			}
		}
		
		return $instance;
	}
	
	/**
	 * Generates the administration form for the widget.
	 *
	 * @since 1.0.0
	 * @param array $instance The array of keys and values for the widget.
	 */
	public function form( $instance ) {
		// Parse incoming $instance into an array and merge it with $defaults
		$instance = wp_parse_args(
			(array) $instance,
			$this->defaults
		);
			
		// Display the admin form
		if ( ! class_exists( 'Walker_Category_Checklist' ) ) {
			require_once ABSPATH . 'wp-admin/includes/template.php';
		}
		
		require_once AIOPOD_PLUGIN_DIR . 'includes/walker-terms-checklist.php';

		include AIOPOD_PLUGIN_DIR . 'widgets/forms/podcasts.php';
	}

	/**
	 * Resolves attributes into a valid, final configuration.
	 * 
	 * This method guarantees that the returned attributes array is safe,
	 * consistent, and ready for query building and rendering.
	 *
	 * @since  1.0.0
	 * @param  array $attributes Raw attributes merged from defaults and user input.
	 * @return array             Fully resolved attributes array.
	 */
	private function resolve_attributes( $attributes ) {
		// Title
		$attributes['title'] = '';

		// Pagination
		if ( 'loadmore' !== $attributes['pagination'] ) {
			$attributes['pagination'] = 'none';
		}
		
		// Return resolved array
		return $attributes;
	}

	/**
	 * Get the form fields.
	 *
	 * @since  1.0.0
	 * @access private
	 * @return array   An associative array of fields.
	 */
	private function get_fields() {
		if ( empty( $this->fields ) ) {
			$this->fields = aiopod_get_shortcode_fields();

			foreach ( $this->fields['podcasts']['sections']['display']['fields'] as $index => $field ) {
				if ( 'pagination' === $field['name'] ) {
					$this->fields['podcasts']['sections']['display']['fields'][ $index ] = array(
						'name'        => 'pagination',
						'label'       => __( 'More Button', 'aio-podcast-studio' ),
						'description' => __( 'Show or hide the "Load More" button.', 'aio-podcast-studio' ),
						'type'        => 'select',
						'options'     => array(							
							'loadmore' => __( 'Show', 'aio-podcast-studio' ),
							'none'     => __( 'Hide', 'aio-podcast-studio' )
						),
						'value'       => 'loadmore'
					);
				}
			}
		}

		return $this->fields;
	}

	/**
	 * Get the default attribute values.
	 *
	 * @since  1.0.0
	 * @access private
	 * @return array  An associative array of attributes.
	 */
	private function get_defaults() {
		if ( empty( $this->defaults ) ) {	
			foreach ( $this->fields['podcasts']['sections'] as $section ) {
				foreach ( $section['fields'] as $field ) {
					$this->defaults[ $field['name'] ] = $field['value'];
				}
			}
			
			$this->defaults['source']        = 'podcasts';
			$this->defaults['title']         = __( 'Podcasts', 'aio-podcast-studio' );
			$this->defaults['count']         = 0;
			$this->defaults['columns']       = 1;
			$this->defaults['limit']         = 4;
			$this->defaults['paged']         = 1;
			$this->defaults['max_num_pages'] = 1;				
			$this->defaults['include']       = '';	
			$this->defaults['exclude']       = '';	
			$this->defaults['pagination']    = 'loadmore';
			$this->defaults['hide_if_empty'] = 0;
		}

		return $this->defaults;
	}
	
}