<?php
/**
 * Masteriyo Advanced Quiz setup.
 *
 * @package Masteriyo\AdvancedQuiz
 *
 * @since 2.4.0
 */

namespace Masteriyo\Addons\AdvancedQuiz;

use Masteriyo\Pro\Addons;
use Masteriyo\Enums\VideoSource;
use Masteriyo\Enums\QuestionType;


defined( 'ABSPATH' ) || exit;

/**
 * Main Masteriyo Advanced Quiz class.
 *
 * @class Masteriyo\Addons\AdvancedQuiz\AdvancedQuizAddon
 */

class AdvancedQuizAddon {
	/**
	 * Initialize the application.
	 *
	 * @since 2.4.0
	 */
	public function init() {
		$addons = new Addons();
		$addons->set_active( 'advanced-quiz' );
		$this->init_hooks();
	}

	/**
	 * Initialize hooks.
	 *
	 * @since 2.4.0
	 */
	public function init_hooks() {
		// Video audio question type.
		add_filter( 'masteriyo_rest_question_schema', array( $this, 'add_files_schema' ) );
		add_action( 'masteriyo_new_question', array( $this, 'save_files_data' ), 10, 2 );
		add_action( 'masteriyo_update_question', array( $this, 'save_files_data' ), 10, 2 );
		add_filter( 'masteriyo_rest_response_question_data', array( $this, 'append_files_data_in_response' ), 10, 4 );
		add_filter( 'masteriyo_rest_response_quiz_builder_data', array( $this, 'append_files_data_in_response' ), 10, 4 );

		// Text answer question type.
		add_filter( 'masteriyo_rest_question_schema', array( $this, 'add_text_answer_schema' ), 11 );
		add_action( 'masteriyo_new_question', array( $this, 'save_text_answer_data' ), 11, 2 );
		add_action( 'masteriyo_update_question', array( $this, 'save_text_answer_data' ), 11, 2 );
		add_filter( 'masteriyo_rest_response_question_data', array( $this, 'append_text_answer_data_in_response' ), 11, 4 );
		add_filter( 'masteriyo_rest_response_quiz_builder_data', array( $this, 'append_text_answer_data_in_response' ), 11, 4 );
	}

	/**
	 * Save text answer data.
	 *
	 * @since 2.4.0
	 *
	 * @param integer $id The question ID.
	 * @param \Masteriyo\Models\Question\Question $object The question object.
	 */
	public function save_text_answer_data( $question_id, $question ) {
		$request = masteriyo_current_http_request();

		if ( null === $request ) {
			return;
		}

		if ( ! isset( $request['max_character'] ) ) {
			return;
		}

		if ( isset( $request['max_character'] ) && isset( $request['type'] ) && QuestionType::TEXT_ANSWER === $request['type'] ) {
			$question->update_meta_data( '_max_character', absint( $request['max_character'] ) );
			$question->save_meta_data();
		}
	}

	/**
	 * Save question (audio/video) files
	 *
	 * @since 2.4.0
	 *
	 * @param integer $id The question ID.
	 * @param \Masteriyo\Models\Question $object The question object.
	 */
	public function save_files_data( $question_id, $question ) {
		$request = masteriyo_current_http_request();

		if ( null === $request ) {
			return;
		}

		if ( ! isset( $request['files'] ) ) {
			return;
		}

		if ( ! in_array( $question->get_type(), array( 'audio', 'video' ), true ) ) {
			return;
		}

		if ( ! isset( $request['files'] ) ) {
			return;
		}

		remove_action( 'masteriyo_update_question', array( $this, 'save_files_data' ) );
		remove_action( 'masteriyo_new_question', array( $this, 'save_files_data' ) );

		$files = $this->prepare_for_database( $request['files'] );

		$question->update_meta_data( '_files', $files );
		$question->save_meta_data();

		add_action( 'masteriyo_new_question', array( $this, 'save_files_data' ), 10, 2 );
		add_action( 'masteriyo_update_question', array( $this, 'save_files_data' ), 10, 2 );
	}

	/**
	 * Process files before saving.
	 *
	 * @since 2.4.0
	 *
	 * @return array
	 */
	protected function prepare_for_database( $files ) {
		$files = array_map(
			function( $file ) {
				return wp_parse_args(
					$file,
					array(
						'id'     => 0,
						'source' => '',
						'url'    => '',
					)
				);
			},
			$files
		);

		$files = array_filter(
			$files,
			function( $file ) {
				if ( VideoSource::SELF_HOSTED === $file['source'] ) {
					$post = get_post( $file['id'] );

					return $post && 'attachment' === $post->post_type;
				}

				return true;
			}
		);

		return $files;
	}

	/**
	 * Filter attachments.
	 *
	 * @since 2.4.0
	 *
	 * @param int[] $attachment ids.
	 * @return int[]
	 */
	protected function filter_attachments( $attachment_ids ) {
		return array_filter(
			$attachment_ids,
			function( $attachment_id ) {
				$post = get_post( $attachment_id );
				return $post && 'attachment' === $post->post_type;
			}
		);
	}

	/**
	 * Append question files to question response.
	 *
	 * @since 2.4.0
	 *
	 * @param array $data Question data.
	 * @param \Masteriyo\Models\Question $question Question object.
	 * @param string $context What the value is for. Valid values are view and edit.
	 * @param \Masteriyo\RestApi\Controllers\Version1\QuestionsController $controller REST questions controller object.
	 */
	public function append_files_data_in_response( $data, $question, $context, $controller ) {
		if ( ! in_array( $question->get_type( $context ), array( 'audio', 'video' ), true ) ) {
			return $data;
		}

		$data['files'] = $this->prepare_for_response( $question, $context );

		return $data;
	}

	/**
	 * Get question video files
	 *
	 * @since 2.4.0
	 *
	 * @param \Masteriyo\Models\Question $question Question object.
	 * @param string $context Request context.
	 *
	 * @return array
	 */
	protected function prepare_for_response( $question, $context ) {
		$files = array_filter(
			is_array( $question->get_meta( '_files' ) ) ? $question->get_meta( '_files' ) : array(),
			function( $file ) {
				if ( VideoSource::SELF_HOSTED === $file['source'] ) {
					$post = get_post( $file['id'] );

					return $post && 'attachment' === $post->post_type;
				}

				return true;
			}
		);

		$files = array_map(
			function( $file ) {
				return wp_parse_args(
					$file,
					array(
						'id'                  => 0,
						'url'                 => '',
						'title'               => '',
						'mime_type'           => '',
						'filename'            => '',
						'file_size'           => 0,
						'formatted_file_size' => '',
						'created_at'          => '',
					)
				);
			},
			$files
		);

		$files = array_map(
			function( $file ) {
				if ( VideoSource::SELF_HOSTED === $file['source'] ) {
					$post                        = get_post( $file['id'] );
					$file['url']                 = wp_get_attachment_url( $post->ID );
					$file['title']               = $post->post_title;
					$file['mime_type']           = $post->post_mime_type;
					$file['filename']            = $post->post_name;
					$file['file_size']           = $post->post_content_filtered;
					$file['formatted_file_size'] = size_format( $file['file_size'] );
					$file['created_at']          = $post->post_date;
				}

				return $file;
			},
			$files
		);

		return $files;
	}

	/**
	 * Append text answer to question response.
	 *
	 * @since 2.4.0
	 *
	 * @param array $data Question data.
	 * @param \Masteriyo\Models\Question\Question $question Question object.
	 * @param string $context What the value is for. Valid values are view and edit.
	 * @param \Masteriyo\RestApi\Controllers\Version1\QuestionsController $controller REST questions controller object.
	 */
	public function append_text_answer_data_in_response( $data, $question, $context, $controller ) {
		if ( QuestionType::TEXT_ANSWER === $question->get_type( $context ) ) {
			$data['max_character'] = $question->get_meta( '_max_character' ) ? absint( $question->get_meta( '_max_character' ) ) : 0;
		}

		return $data;
	}

	/**
	 * Add files fields to question schema
	 *
	 * @since 2.4.0
	 *
	 * @param array $schema
	 * @return array
	 */
	public function add_files_schema( $schema ) {
		$schema = wp_parse_args(
			$schema,
			array(
				'files' => array(
					'description' => __( 'Question files only valid for (audio/video) type', 'learning-management-system' ),
					'type'        => 'array',
					'context'     => array( 'view', 'edit' ),
					'items'       => array(
						'type'       => 'object',
						'properties' => array(
							'id'                  => array(
								'description' => __( 'Question file ID', 'learning-management-system' ),
								'type'        => 'integer',
								'default'     => 0,
								'context'     => array( 'view', 'edit' ),
							),
							'title'               => array(
								'description' => __( 'Question file title', 'learning-management-system' ),
								'type'        => 'string',
								'context'     => array( 'view', 'edit' ),
								'readonly'    => true,
							),
							'url'                 => array(
								'description' => __( 'Question file URL', 'learning-management-system' ),
								'type'        => 'string',
								'format'      => 'uri',
								'context'     => array( 'view', 'edit' ),
								'readonly'    => true,
							),
							'mime_type'           => array(
								'description' => __( 'Question file mime type', 'learning-management-system' ),
								'type'        => 'string',
								'context'     => array( 'view', 'edit' ),
								'readonly'    => true,
							),
							'file_size'           => array(
								'description' => __( 'Question file file size', 'learning-management-system' ),
								'type'        => 'integer',
								'context'     => array( 'view', 'edit' ),
								'readonly'    => true,
							),
							'formatted_file_size' => array(
								'description' => __( 'Question file formatted file size', 'learning-management-system' ),
								'type'        => 'string',
								'context'     => array( 'view', 'edit' ),
								'readonly'    => true,
							),
							'created_at'          => array(
								'description' => __( 'Question file creation/upload date.', 'learning-management-system' ),
								'type'        => 'string',
								'format'      => 'date-time',
								'context'     => array( 'view', 'edit' ),
								'readonly'    => true,
							),
							'source'              => array(
								'description' => __( 'Question video source.', 'learning-management-system' ),
								'type'        => 'string',
								'context'     => array( 'view', 'edit' ),
								'enum'        => VideoSource::all(),
							),
						),
					),
				),
			)
		);

		return $schema;
	}

	/**
	 * Add text answer fields to question schema.
	 *
	 * @since 2.4.0
	 *
	 * @param array $schema
	 * @return array
	 */
	public function add_text_answer_schema( $schema ) {
		$schema = wp_parse_args(
			$schema,
			array(
				'max_character' => array(
					'description' => __( 'Maximum character for text answer.', 'learning-management-system' ),
					'type'        => 'number',
					'context'     => array( 'view', 'edit' ),
				),
			)
		);

		return $schema;
	}
}
