<?php
/**
 * Fill in the blanks question model.
 *
 * @since 2.4.7
 *
 * @package Masteriyo\Models
 */

namespace Masteriyo\Addons\AdvancedQuiz\Models;

use stdClass;
use Masteriyo\Models\Question\Question;
use Masteriyo\Models\Question\QuestionInterface;

defined( 'ABSPATH' ) || exit;

/**
 * Fill in the blanks question model.
 *
 * @since 2.4.7
 */
class FillInTheBlanks extends Question implements QuestionInterface {
	/**
	 * Question type.
	 *
	 * @since 2.4.7
	 *
	 * @var string $type Question type.
	 */
	protected $type = 'fill-in-the-blanks';

	/**
	 * Return true if the answer should be manually reviewed and manually assigned points.
	 *
	 * @since 2.9.1
	 *
	 * @return boolean
	 */
	public function is_reviewable() {
		return true;
	}

	/**
	 * Check whether the chosen answer is correct or not.
	 *
	 * @since 2.4.7
	 *
	 * @param array  $chosen_answers Answer chosen by user.
	 * @param string $context Options: 'edit', 'view'.
	 *
	 * @return bool
	 */
	public function check_answer( $chosen_answers, $context = 'edit' ) {
		$correct        = true;
		$chosen_answers = array_map( 'masteriyo_strtolower', (array) $chosen_answers );

		// Remove spaces if any on answer.
		$trimmed_answers = array_map( 'trim', (array) $chosen_answers );

		// Extract the blanks from the stored answers and convert it to array.
		$answers = $this->get_correct_answers( 'edit' );
		if ( count( $answers ) === count( $trimmed_answers ) ) {
			foreach ( $trimmed_answers as $index => $chosen_answer ) {
				$lower_case_answers = array_map( 'masteriyo_strtolower', $answers[ $index ] );

				if ( ! in_array( $chosen_answer, $lower_case_answers, true ) ) {
					$correct = false;
					break;
				}
			}
		} else {
			$correct = false;
		}

		/**
		 * Filters boolean: true if the chosen answer is correct.
		 *
		 * @since 2.4.7
		 *
		 * @param boolean $bool true if the chosen answer is correct.
		 * @param array $chosen_answer Chosen answer.
		 * @param string $context Context.
		 * @param \Masteriyo\Addons\AdvancedQuiz\Models\FillInTheBlanks $this Fill in the blanks question object.
		 */
		return apply_filters( "masteriyo_question_check_answer_{$this->type}", $correct, $chosen_answers, $context, $this );
	}

	/**
	 * Get correct answers only.
	 *
	 * @since 2.4.7
	 *
	 * @return mixed
	 */
	public function get_correct_answers() {
		$re = '/{{.+}}/mU';

		$answers = $this->get_answers( 'edit' );
		$answers = is_array( $answers ) ? join( $answers ) : $answers;
		preg_match_all( $re, $answers, $matches, PREG_SET_ORDER, 0 );
		$matches = masteriyo_array_flatten( $matches );

		$matches = array_map(
			function( $match ) {
				$match = masteriyo_strtolower( $match );
				$match = str_replace( '{', '', $match );
				$match = str_replace( '}', '', $match );
				$match = explode( '|', $match );
				$match = array_map( 'trim', $match );

				return $match;
			},
			$matches
		);

		return $matches;
	}
}
