<?php
/**
 * Manage short codes
 *
 * @package Tutor\ShortCode
 * @author Themeum <support@themeum.com>
 * @link https://themeum.com
 * @since 1.0.0
 */

namespace TUTOR;

use Tutor\Models\CourseModel;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Short code class
 *
 * @since 1.0.0
 */
class Shortcode {

	/**
	 * Instructor page design layouts
	 *
	 * @since 1.0.0
	 *
	 * @var array
	 */
	private $instructor_layout = array(
		'default',
		'cover',
		'minimal',
		'portrait-horizontal',
		'minimal-horizontal',
	);

	/**
	 * Register hooks
	 *
	 * @since 1.0.0
	 */
	public function __construct() {
		add_shortcode( 'tutor_student_registration_form', array( $this, 'student_registration_form' ) );
		add_shortcode( 'tutor_dashboard', array( $this, 'tutor_dashboard' ) );
		add_shortcode( 'tutor_instructor_registration_form', array( $this, 'instructor_registration_form' ) );
		add_shortcode( 'tutor_course', array( $this, 'tutor_course' ) );

		add_shortcode( 'tutor_instructor_list', array( $this, 'tutor_instructor_list' ) );
		add_action( 'wp_ajax_load_filtered_instructor', array( $this, 'load_filtered_instructor' ) );
		add_action( 'wp_ajax_nopriv_load_filtered_instructor', array( $this, 'load_filtered_instructor' ) );

		add_shortcode( 'tutor_cart', array( $this, 'tutor_cart_page' ) );
		add_shortcode( 'tutor_checkout', array( $this, 'tutor_checkout_page' ) );

		/**
		 * Load more categories
		 *
		 * @since 2.0.0
		 */
		add_action( 'wp_ajax_show_more', array( $this, 'show_more' ) );
		add_action( 'wp_ajax_nopriv_show_more', array( $this, 'show_more' ) );
	}

	/**
	 *  Instructor Registration Shortcode
	 *
	 * @since 1.0.0
	 *
	 * @return mixed
	 */
	public function student_registration_form() {
		ob_start();
		if ( is_user_logged_in() ) {
			tutor_load_template( 'dashboard.logged-in' );
		} else {
			tutor_load_template( 'dashboard.registration' );
		}
		return apply_filters( 'tutor/student/register', ob_get_clean() );
	}

	/**
	 * Tutor Dashboard for students
	 *
	 * @since 1.0.0
	 *
	 * @return mixed
	 */
	public function tutor_dashboard() {
		global $wp_query;

		ob_start();
		if ( is_user_logged_in() ) {
			/**
			 * Added isset() Condition to avoid infinite loop since v.1.5.4
			 * This has cause error by others plugin, Such AS SEO
			 */

			if ( ! isset( $wp_query->query_vars['tutor_dashboard_page'] ) ) {
				tutor_load_template( 'dashboard', array( 'is_shortcode' => true ) );
			}
		} else {
			/**
			 * If user not logged in show login form instead of
			 * popup sign-in button
			 *
			 * @since 2.1.3
			 */
			$login_url   = tutor_utils()->get_option( 'enable_tutor_native_login', null, true, true ) ? '' : wp_login_url( tutor()->current_url );
			$signin_link = '<a data-login_url="' . esc_url( $login_url ) . '" href="#" class="tutor-open-login-modal">' . __( 'Sign-In', 'tutor' ) . '</a>';
			/* translators: %s is anchor link for signin */
			echo sprintf( __( 'Please %s to view this page', 'tutor' ), $signin_link ); //phpcs:ignore
		}
		return apply_filters( 'tutor_dashboard/index', ob_get_clean() );
	}

	/**
	 * Instructor Registration Shortcode
	 *
	 * @since v.1.0.0
	 *
	 * @return mixed
	 */
	public function instructor_registration_form() {
		ob_start();
		if ( is_user_logged_in() ) {
			tutor_load_template( 'dashboard.instructor.logged-in' );
		} else {
			tutor_load_template( 'dashboard.instructor.registration' );
		}
		return apply_filters( 'tutor_dashboard/student/index', ob_get_clean() );
	}

	/**
	 * Short code for getting course
	 *
	 * @since 1.0.0
	 *
	 * @param mixed $atts attributes.
	 *
	 * @return string
	 */
	public function tutor_course( $atts ) {
		$a = shortcode_atts(
			array(
				'post_type'   => apply_filters( 'tutor_course_archive_post_types', array( tutor()->course_post_type ) ),
				'post_status' => 'publish',

				'id'          => '',
				'exclude_ids' => '',
				'category'    => '',

				'orderby'     => 'ID',
				'order'       => 'DESC',
				'count'       => tutils()->get_option( 'courses_per_page', 12 ),
				'paged'       => get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1,
			),
			$atts
		);

		$a = apply_filters( 'tutor_get_course_list_filter_args', $a );

		$supported_filters         = tutor_utils()->get_option( 'supported_course_filters', array() );
		$course_filter_category    = array();
		$course_filter_exclude_ids = array();
		$course_filter_post_ids    = array();

		if ( ! empty( $a['id'] ) ) {
			$ids           = (array) explode( ',', $a['id'] );
			$a['post__in'] = $ids;

			if ( is_array( $ids ) && count( $ids ) && ! wp_doing_ajax() ) {
				$_GET['tutor-course-filter-post-ids'] = $ids;
				$course_filter_post_ids               = $ids;
			}
		}

		if ( ! empty( $a['exclude_ids'] ) ) {
			$exclude_ids       = (array) explode( ',', $a['exclude_ids'] );
			$a['post__not_in'] = $exclude_ids;
			if ( is_array( $exclude_ids ) && count( $exclude_ids ) && ! wp_doing_ajax() ) {
				$_GET['tutor-course-filter-exclude-ids'] = $exclude_ids;
				$course_filter_exclude_ids               = $exclude_ids;
			}
		}
		if ( ! empty( $a['category'] ) ) {
			$category = (array) explode( ',', $a['category'] );

			$a['tax_query'] = array();

			$category_ids = array_filter(
				$category,
				function ( $id ) {
					return is_numeric( $id );
				}
			);

			$category_names = array_filter(
				$category,
				function ( $id ) {
					return ! is_numeric( $id );
				}
			);

			if ( ! empty( $category_ids ) ) {
				$a['tax_query'] = array(
					array(
						'taxonomy' => CourseModel::COURSE_CATEGORY,
						'field'    => 'term_id',
						'terms'    => $category_ids,
						'operator' => 'IN',
					),
				);

				if ( is_array( $category_ids ) && count( $category_ids ) && ! wp_doing_ajax() ) {
					$_GET['tutor-course-filter-category'] = $category_ids;
					$course_filter_category               = $category_ids;
					unset( $supported_filters['category'] );
				}
			}

			if ( ! empty( $category_names ) ) {
				$a['tax_query'] = array(
					array(
						'taxonomy' => CourseModel::COURSE_CATEGORY,
						'field'    => 'name',
						'terms'    => $category_names,
						'operator' => 'IN',
					),
				);
			}
		}
		$a['posts_per_page'] = (int) $a['count'];

		wp_reset_query();
		$the_query = new \WP_Query( $a );

		/**
		 * Pagination & course filter handle from query param on page load (without ajax)
		 *
		 * @since 2.4.0
		 */
		$get = Input::has( 'course_filter' ) ? Input::sanitize_array( $_GET ) : array();
		if ( Input::has( 'course_filter' ) ) {
			$filter    = ( new \Tutor\Course_Filter( false ) )->load_listing( $get, true );
			$the_query = new \WP_Query( $filter );
		}

		// Load the renderer now.
		ob_start();

		if ( $the_query->have_posts() ) {
			tutor_load_template(
				'archive-course-init',
				array(
					'course_filter'             => isset( $atts['course_filter'] ) && 'on' === $atts['course_filter'],
					'supported_filters'         => $supported_filters,
					'loop_content_only'         => false,
					'column_per_row'            => isset( $atts['column_per_row'] ) ? $atts['column_per_row'] : null,
					'course_per_page'           => $a['posts_per_page'],
					'show_pagination'           => isset( $atts['show_pagination'] ) && 'on' === $atts['show_pagination'],
					'the_query'                 => $the_query,
					'current_page'              => isset( $get['current_page'] ) ? (int) $get['current_page'] : 1,
					'course_filter_category'    => ! empty( $course_filter_category ) ? json_encode( $course_filter_category ) : null,
					'course_filter_exclude_ids' => ! empty( $course_filter_exclude_ids ) ? json_encode( $course_filter_exclude_ids ) : null,
					'course_filter_post_ids'    => ! empty( $course_filter_post_ids ) ? json_encode( $course_filter_post_ids ) : null,
				)
			);
		} else {
			tutor_utils()->tutor_empty_state( tutor_utils()->not_found_text() );
		}

		$output = ob_get_clean();
		wp_reset_postdata();
		return $output;
	}

	/**
	 * Prepare instructor list
	 *
	 * @param string $current_page current page.
	 * @param mixed  $atts atts for query.
	 * @param array  $cat_ids category ids.
	 * @param string $keyword search keyword.
	 *
	 * @return array
	 */
	private function prepare_instructor_list( $current_page, $atts, $cat_ids = array(), $keyword = '' ) {

		$default_pagination = tutor_utils()->get_option( 'pagination_per_page', 9 );
		$limit              = (int) sanitize_text_field( tutor_utils()->array_get( 'count', $atts, $default_pagination ) );
		$page               = $current_page - 1;
		$rating_filter      = Input::post( 'rating_filter', '' );

		/**
		 * Sort by Relevant | New | Popular
		 *
		 * @since 2.0.0
		 */
		$short_by = Input::post( 'short_by', 'ASC' );

		$instructors       = tutor_utils()->get_instructors( $limit * $page, $limit, $keyword, '', '', $short_by, 'approved', $cat_ids, $rating_filter );
		$instructors_count = tutor_utils()->get_instructors( $limit * $page, $limit, $keyword, '', '', $short_by, 'approved', $cat_ids, $rating_filter, true );

		$layout      = sanitize_text_field( tutor_utils()->array_get( 'layout', $atts, '' ) );
		$layout      = in_array( $layout, $this->instructor_layout ) ? $layout : tutor_utils()->get_option( 'instructor_list_layout', $this->instructor_layout[0] );
		$default_col = tutor_utils()->get_option( 'courses_col_per_row', 3 );

		$payload = array(
			'instructors'       => is_array( $instructors ) ? $instructors : array(),
			'instructors_count' => $instructors_count,
			'column_count'      => sanitize_text_field( tutor_utils()->array_get( 'column_per_row', $atts, $default_col ) ),
			'layout'            => $layout,
			'limit'             => $limit,
			'current_page'      => $current_page,
			'filter'            => $atts,
		);

		return $payload;
	}

	/**
	 * Short code for getting instructors
	 *
	 * @param array $atts array of attrs.
	 *
	 * @return string
	 */
	public function tutor_instructor_list( $atts ) {
		! is_array( $atts ) ? $atts = array() : 0;

		$current_page = (int) tutor_utils()->array_get( 'instructor-page', $_GET, 1 );
		$current_page = Input::get( 'instructor-page', 1, Input::TYPE_INT );
		$current_page = $current_page >= 1 ? $current_page : 1;

		$show_filter         = isset( $atts['filter'] ) ? 'on' === $atts['filter'] : tutor_utils()->get_option( 'instructor_list_show_filter', false );
		$category_limit      = (int) isset( $atts['category_limit'] ) ? $atts['category_limit'] : 0;
		$hide_empty_category = isset( $atts['hide_empty_category'] ) ? '1' == $atts['hide_empty_category'] : false;
		$atts['show_filter'] = $show_filter;

		// Get instructor list to sow.
		$payload                = $this->prepare_instructor_list( $current_page, $atts );
		$payload['show_filter'] = $show_filter;

		ob_start();
		tutor_load_template( 'shortcode.tutor-instructor', $payload );
		$content = ob_get_clean();

		if ( $show_filter ) {
			$course_taxonomy = CourseModel::COURSE_CATEGORY;
			$term_args       = array(
				'taxonomy'   => $course_taxonomy,
				'hide_empty' => $hide_empty_category,
				'orderby'    => 'count',
				'order'      => 'DESC',
				'number'     => $category_limit,
			);

			$course_cats = get_terms( $term_args );

			$attributes = $payload;
			unset( $attributes['instructors'] );

			$payload = array(
				'show_filter' => $show_filter,
				'content'     => $content,
				'categories'  => $course_cats,
				'attributes'  => array_merge( $atts, $attributes ),
			);

			ob_start();

			tutor_load_template( 'shortcode.instructor-filter', $payload );

			$content = ob_get_clean();
		}

		return $content;
	}

	/**
	 * Load more categories
	 * handle ajax request
	 *
	 * @since 2.0.0
	 *
	 * @return void send wp_json response
	 */
	public function show_more() {
		global $wpdb;
		tutor_utils()->checking_nonce();
		$term_id         = Input::post( 'term_id', 0, Input::TYPE_INT );
		$limit           = 8;
		$course_taxonomy = CourseModel::COURSE_CATEGORY;

		$remaining_categories = $wpdb->get_var(
			$wpdb->prepare(
				"SElECT 
					COUNT(*) AS total 
				FROM {$wpdb->terms} AS term
					INNER JOIN {$wpdb->term_taxonomy} AS taxonomy
						ON taxonomy.term_id = term.term_id AND taxonomy.taxonomy = %s
				WHERE term.term_id < %d
				ORDER BY term.term_id DESC
				",
				$course_taxonomy,
				$term_id
			)
		);

		$add_categories = $wpdb->get_results(
			$wpdb->prepare(
				"SElECT
					* 
				FROM {$wpdb->terms} term
				INNER JOIN {$wpdb->term_taxonomy} as taxonomy
					ON taxonomy.term_id = term.term_id AND taxonomy.taxonomy = %s
				WHERE term.term_id < %d
				ORDER BY term.term_id DESC
				LIMIT %d
				",
				$course_taxonomy,
				$term_id,
				$limit
			)
		);
		$show_more      = false;
		if ( $remaining_categories > $limit ) {
			$show_more = true;
		}
		$response = array(
			'categories' => $add_categories,
			'show_more'  => $show_more,
			'remaining'  => $remaining_categories,
		);
		wp_send_json_success( $response );
		exit;
	}

	/**
	 * Filter instructor
	 *
	 * @since 1.0.0
	 *
	 * @return void send wp_json response
	 */
	public function load_filtered_instructor() {
		tutor_utils()->checking_nonce();

		// phpcs:disable WordPress.Security.NonceVerification.Missing --nonce already verified
		$_post        = tutor_sanitize_data( $_POST );
		$current_page = (int) sanitize_text_field( tutor_utils()->array_get( 'current_page', $_post, 1 ) );
		$keyword      = (string) sanitize_text_field( tutor_utils()->array_get( 'keyword', $_post, '' ) );

		$category = (array) tutor_utils()->array_get( 'category', $_post, array() );
		$category = array_filter(
			$category,
			function ( $cat ) {
				return is_numeric( $cat );
			}
		);

		$data = $this->prepare_instructor_list( $current_page, $_post, $category, $keyword );

		ob_start();
		tutor_load_template( 'shortcode.tutor-instructor', $data );
		wp_send_json_success( array( 'html' => ob_get_clean() ) );
		exit;
	}

	/**
	 * Tutor Cart Shortcode
	 *
	 * @since v.3.0.0
	 *
	 * @return mixed
	 */
	public function tutor_cart_page() {
		ob_start();
		tutor_load_template( 'ecommerce.cart' );
		return apply_filters( 'tutor_ecommerce/cart', ob_get_clean() );
	}

	/**
	 * Tutor Checkout Shortcode
	 *
	 * @since v.3.0.0
	 *
	 * @return mixed
	 */
	public function tutor_checkout_page() {
		ob_start();
		tutor_load_template( 'ecommerce.checkout' );
		return apply_filters( 'tutor_ecommerce/checkout', ob_get_clean() );
	}
}
