<?php
/**
 * Grade Result model.
 *
 * @since 2.5.20
 *
 * @package Masteriyo\Addons\Gradebook
 */

namespace Masteriyo\Addons\Gradebook\Models;

use Masteriyo\Addons\Gradebook\Enums\GradeResultType;
use Masteriyo\Addons\Gradebook\Query\GradeQuery;
use Masteriyo\Addons\Gradebook\Query\GradeResultQuery;
use Masteriyo\Database\Model;
use Masteriyo\Repository\RepositoryInterface;

defined( 'ABSPATH' ) || exit;

/**
 * Grade Result model (post type).
 *
 * @since 2.5.20
 */
class GradeResult extends Model {

	/**
	 * This is the name of this object type.
	 *
	 * @since 2.5.20
	 *
	 * @var string
	 */
	protected $object_type = 'grade_result';

	/**
	 * Cache group.
	 *
	 * @since 2.5.20
	 *
	 * @var string
	 */
	protected $cache_group = 'grades_results';

	/**
	 * Stores grade data.
	 *
	 * @since 2.5.20
	 *
	 * @var array
	 */
	protected $data = array(
		'user_id'            => 0,
		'parent_id'          => 0,
		'item_id'            => 0,
		'item_type'          => '',
		'item_name'          => 0,
		'status'             => false,
		'grade_id'           => 0,
		'grade_name'         => '',
		'grade_color'        => '',
		'grade_point'        => 0,
		'earned_grade_point' => 0,
		'earned_percent'     => 0,
		'weight'             => 1,
		'created_at'         => null,
		'modified_at'        => null,
	);

	/**
	 * Constructor.
	 *
	 * @since 2.5.20
	 *
	 * @param RepositoryInterface $grade_result_repository Grade Result Repository,
	 */
	public function __construct( RepositoryInterface $grade_result_repository ) {
		$this->repository = $grade_result_repository;
	}

	/*
	|--------------------------------------------------------------------------
	| Non-CRUD
	|----------

	/**
	 * Get the object type.
	 *
	 * @since 2.5.20
	 *
	 * @return string
	 */
	public function get_object_type() {
		return $this->object_type;
	}

	/**
	 * Return table name.
	 *
	 * @since 2.5.20
	 *
	 * @return string
	 */
	public function get_table_name() {
		global $wpdb;

		return "{$wpdb->prefix}masteriyo_gradebook_results";
	}

	/**
	 * Return parent grade result (course).
	 *
	 * @since 2.5.20
	 *
	 * @return \Masteriyo\Addons\Gradebook\Models\GradeResult|null
	 */
	public function get_parent() {
		return masteriyo_get_grade_result( $this->get_parent_id() );
	}

	/**
	 * Return course this grade result belongs to.
	 *
	 * @since 2.5.20
	 *
	 * @return \Masteriyo\Models\Course|null
	 */
	public function get_course() {
		$course = null;
		$parent = GradeResultType::COURSE === $this->get_item_type() ? $this : $this->get_parent();

		if ( $parent ) {
			$course = masteriyo_get_course( $parent->get_item_id() );
		}

		return $course;
	}

	/**
	 * Return course ID.
	 *
	 * @since 2.5.20
	 *
	 * @return int
	 */
	public function get_course_id() {
		$course_id = 0;
		$parent    = GradeResultType::COURSE === $this->get_item_type() ? $this : $this->get_parent();

		if ( $parent ) {
			$course_id = $parent->get_item_id();
		}

		return $course_id;
	}


	/**
	 * Return children.
	 *
	 * @since 2.5.20
	 *
	 * @return \Masteriyo\Addons\Gradebook\Models\GradeResult[]
	 */
	public function get_children() {
		$query = new GradeResultQuery(
			array(
				'parent'    => $this->get_id(),
				'item_type' => GradeResultType::all(),
				'orderby'   => 'created_at',
				'page'      => 0,
				'per_page'  => 0,
			)
		);

		return $query->get_grade_results();
	}

	/**
	 * Return grade id.
	 *
	 * @since 2.5.20
	 *
	 * @return string
	 */
	public function get_grade_id( $context = 'view' ) {
		return $this->get_prop( 'grade_id', $context );
	}

	/*
	|--------------------------------------------------------------------------
	| Getters
	|--------------------------------------------------------------------------
	*/

	/**
	 * Get user id.
	 *
	 * @since  2.5.20
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 *
	 * @return string
	 */
	public function get_user_id( $context = 'view' ) {
		return $this->get_prop( 'user_id', $context );
	}


	/**
	 * Get parent id.
	 *
	 * @since  2.5.20
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 *
	 * @return string
	 */
	public function get_parent_id( $context = 'view' ) {
		return $this->get_prop( 'parent_id', $context );
	}

	/**
	 * Get item id.
	 *
	 * @since  2.5.20
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 *
	 * @return string
	 */
	public function get_item_id( $context = 'view' ) {
		return $this->get_prop( 'item_id', $context );
	}

	/**
	 * Get item type.
	 *
	 * @since  2.5.20
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 *
	 * @return string
	 */
	public function get_item_type( $context = 'view' ) {
		return $this->get_prop( 'item_type', $context );
	}

	/**
	 * Get item name.
	 *
	 * @since  2.5.20
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 *
	 * @return string
	 */
	public function get_item_name( $context = 'view' ) {
		return $this->get_prop( 'item_name', $context );
	}

	/**
	 * Get status.
	 *
	 * @since  2.5.20
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 *
	 * @return string
	 */
	public function get_status( $context = 'view' ) {
		return $this->get_prop( 'status', $context );
	}

	/**
	 * Get grade name.
	 *
	 * @since  2.5.20
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 *
	 * @return string
	 */
	public function get_grade_name( $context = 'view' ) {
		return $this->get_prop( 'grade_name', $context );
	}

	/**
	 * Get grade color.
	 *
	 * @since  2.5.20
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 *
	 * @return string
	 */
	public function get_grade_color( $context = 'view' ) {
		return $this->get_prop( 'grade_color', $context );
	}


	/**
	 * Get grade point.
	 *
	 * @since  2.5.20
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 *
	 * @return float
	 */
	public function get_grade_point( $context = 'view' ) {
		return $this->get_prop( 'grade_point', $context );
	}

	/**
	 * Get earned grade point.
	 *
	 * @since  2.5.20
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 *
	 * @return float
	 */
	public function get_earned_grade_point( $context = 'view' ) {
		return $this->get_prop( 'earned_grade_point', $context );
	}

	/**
	 * Get earned percent.
	 *
	 * @since  2.5.20
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 *
	 * @return float
	 */
	public function get_earned_percent( $context = 'view' ) {
		return $this->get_prop( 'earned_percent', $context );
	}

	/**
	 * Get weight.
	 *
	 * @since  2.5.20
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 *
	 * @return int
	 */
	public function get_weight( $context = 'view' ) {
		return $this->get_prop( 'weight', $context );
	}

	/**
	 * Get grade result created date.
	 *
	 * @since  2.5.20
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 *
	 * @return \Masteriyo\DateTime|null object if the date is set or null if there is no date.
	 */
	public function get_created_at( $context = 'view' ) {
		return $this->get_prop( 'created_at', $context );
	}

	/**
	 * Get grade result modified date.
	 *
	 * @since  2.5.20
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 *
	 * @return \Masteriyo\DateTime|null object if the date is set or null if there is no date.
	 */
	public function get_modified_at( $context = 'view' ) {
		return $this->get_prop( 'modified_at', $context );
	}

	/**
	 * Returns whether review is allowed or not..
	 *
	 * @since  2.5.20
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return string price
	 */
	public function get_reviews_allowed( $context = 'view' ) {
		return $this->get_prop( 'reviews_allowed', $context );
	}


	/**
	 * Get date on sale from.
	 *
	 * @since  2.5.20
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return Masteriyo\DateTime|NULL object if the date is set or null if there is no date.
	 */
	public function get_date_on_sale_from( $context = 'view' ) {
		return $this->get_prop( 'date_on_sale_from', $context );
	}

	/**
	 * Get date on sale to.
	 *
	 * @since  2.5.20
	 * @param  string $context What the value is for. Valid values are view and edit.
	 * @return Masteriyo\DateTime|NULL object if the date is set or null if there is no date.
	 */
	public function get_date_on_sale_to( $context = 'view' ) {
		return $this->get_prop( 'date_on_sale_to', $context );
	}

	/*
	|--------------------------------------------------------------------------
	| Setters
	|--------------------------------------------------------------------------
	*/

	/**
	 * Set user id.
	 *
	 * @since 2.5.20
	 *
	 * @param string $user_id User ID.
	 */
	public function set_user_id( $user_id ) {
		$this->set_prop( 'user_id', absint( $user_id ) );
	}

	/**
	 * Set parent id.
	 *
	 * @since 2.5.20
	 *
	 * @param string $parent_id Parent ID.
	 */
	public function set_parent_id( $parent_id ) {
		$this->set_prop( 'parent_id', absint( $parent_id ) );
	}

	/**
	 * Set item id.
	 *
	 * @since 2.5.20
	 *
	 * @param string $item_id Item ID.
	 */
	public function set_item_id( $item_id ) {
		$this->set_prop( 'item_id', absint( $item_id ) );
	}

	/**
	 * Set item type.
	 *
	 * @since 2.5.20
	 *
	 * @param string $item_type Item type
	 */
	public function set_item_type( $item_type ) {
		$this->set_prop( 'item_type', $item_type );
	}

	/**
	 * Set item name.
	 *
	 * @since 2.5.20
	 *
	 * @param string $item_name Item name
	 */
	public function set_item_name( $item_name ) {
		$this->set_prop( 'item_name', $item_name );
	}

	/**
	 * Set status.
	 *
	 * @since 2.5.20
	 *
	 * @param string $status Status
	 */
	public function set_status( $status ) {
		$this->set_prop( 'status', $status );
	}

	/**
	 * Set grade name.
	 *
	 * @since 2.5.20
	 *
	 * @param string $grade_name Grade name
	 */
	public function set_grade_name( $grade_name ) {
		$this->set_prop( 'grade_name', $grade_name );
	}

	/**
	 * Set grade color.
	 *
	 * @since 2.5.20
	 *
	 * @param string $grade_color Grade color
	 */
	public function set_grade_color( $grade_color ) {
		$this->set_prop( 'grade_color', $grade_color );
	}

	/**
	 * Set grade id.
	 *
	 * @since 2.5.20
	 *
	 * @param string $grade_id Grade id
	 */
	public function set_grade_id( $grade_id ) {
		$this->set_prop( 'grade_id', absint( $grade_id ) );
	}

	/**
	 * Set grade point.
	 *
	 * @since 2.5.20
	 *
	 * @param float $grade_point Grade point
	 */
	public function set_grade_point( $grade_point ) {
		$this->set_prop( 'grade_point', masteriyo_round( $grade_point, 2 ) );
	}

	/**
	 * Set earned grade point.
	 *
	 * @since 2.5.20
	 *
	 * @param float $earned_grade_point earned_Grade point
	 */
	public function set_earned_grade_point( $earned_grade_point ) {
		$this->set_prop( 'earned_grade_point', masteriyo_round( $earned_grade_point, 2 ) );
	}

	/**
	 * Set earned grade point.
	 *
	 * @since 2.5.20
	 *
	 * @param float $earned_percent earned_Grade point
	 */
	public function set_earned_percent( $earned_percent ) {
		$this->set_prop( 'earned_percent', masteriyo_round( $earned_percent, 2 ) );
	}

	/**
	 * Set grade weight.
	 *
	 * @since 2.5.20
	 *
	 * @param float $weight Weight
	 */
	public function set_weight( $weight ) {
		$this->set_prop( 'weight', absint( $weight ) );
	}

	/**
	 * Set grade result created date.
	 *
	 * @since 2.5.20
	 *
	 * @param string|integer|null $date UTC timestamp, or ISO 8601 DateTime. If the DateTime string has no timezone or offset, WordPress site timezone will be assumed. Null if their is no date.
	 */
	public function set_created_at( $date ) {
		$this->set_date_prop( 'created_at', $date );
	}

	/**
	 * Set grade result modified date.
	 *
	 * @since 2.5.20
	 *
	 * @param string|integer|null $date UTC timestamp, or ISO 8601 DateTime. If the DateTime string has no timezone or offset, WordPress site timezone will be assumed. Null if their is no date.
	 */
	public function set_modified_at( $date ) {
		$this->set_date_prop( 'modified_at', $date );
	}
}
