<?php
/**
 * Zoom model.
 *
 * @since 2.5.19
 *
 * @package Masteriyo\Addons\Zoom
 */

namespace Masteriyo\Addons\Zoom\Models;

use DateTimeZone;
use Masteriyo\Addons\Zoom\Enums\ZoomMeetingStatus;
use Masteriyo\Addons\Zoom\Enums\ZoomMeetingType;
use Masteriyo\Addons\Zoom\Enums\ZoomRecordingType;
use Masteriyo\Addons\Zoom\Repository\ZoomRepository;
use Masteriyo\Database\Model;
use Masteriyo\DateTime;

defined( 'ABSPATH' ) || exit;

/**
 * Zoom model (post type).
 *
 * @since 2.5.19
 */
class Zoom extends Model {

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

	/**
	 * Post type.
	 *
	 * @since 2.5.19
	 *
	 * @var string
	 */
	protected $post_type = 'mto-zoom';

	/**
	 * Cache group.
	 *
	 * @since 2.5.19
	 *
	 * @var string
	 */
	protected $cache_group = 'zooms';

	/**
	 * Stores Zoom data.
	 *
	 * @since 2.5.19
	 *
	 * @var array
	 */
	protected $data = array(
		'name'               => '',
		'description'        => '',
		'password'           => '',
		'status'             => '',
		'author_id'          => 0,
		'course_id'          => 0,
		'menu_order'         => 0,
		'parent_id'          => 0,
		'duration'           => 0,
		'join_before_host'   => false,
		'focus_mode'         => false,
		'time_zone'          => '',
		'mute_upon_entry'    => false,
		'participant_video'  => false,
		'record'             => ZoomRecordingType::NONE,
		'close_registration' => false,
		'created_at'         => '',
		'modified_at'        => '',
		'meeting_id'         => '',
		'start_url'          => '',
		'expires_at'         => null,
		'starts_at'          => null,
		'join_url'           => '',
		'host_video'         => false,
		'type'               => ZoomMeetingType::SCHEDULED,
	);

	/**
	 * Get the zoom session if ID
	 *
	 * @since 2.5.19
	 *
	 * @param \Masteriyo\Addons\Zoom\Repository\ZoomRepository $zoom_repository Zoom Repository.
	*/
	public function __construct( ZoomRepository $zoom_repository ) {
		$this->repository = $zoom_repository;
	}

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

	/**
	 * Get the zoom session title. For courses this is the course name.
	 *
	 * @since 2.5.19
	 *
	 * @return string
	 */
	public function get_title() {
		/**
		 * Filters zoom title.
		 *
		 * @since 2.5.19
		 *
		 * @param string $title Zoom title.
		 * @param Masteriyo\Models\Zoom $zoom Zoom object.
		 */
		return apply_filters( 'masteriyo_zoom_title', $this->get_name(), $this );
	}

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

	/**
	 * Zoom permalink.
	 *
	 * @return string
	 */
	public function get_permalink() {
		return get_permalink( $this->get_id() );
	}

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

	/**
	 * Get the post type.
	 *
	 * @since 2.5.19
	 *
	 * @return string
	 */
	public function get_post_type() {
		return $this->post_type;
	}

	/**
	 * Get post preview link.
	 *
	 * @since 2.5.19
	 *
	 * @return string
	 */
	public function get_post_preview_link() {
		$preview_link = get_preview_post_link( $this->get_id() );

		/**
		 * Zoom post preview link.
		 *
		 * @since 2.5.19
		 *
		 * @param string $url Preview URL.
		 * @param Masteriyo\Models\Zoom $Zoom Zoom object.
		 */
		return apply_filters( 'masteriyo_zoom_post_preview_link', $preview_link, $this );
	}

	/**
	 * Get preview link in learn page.
	 *
	 * @since 2.5.19
	 *
	 * @return string
	 */
	public function get_preview_link() {
		$preview_link = '';
		$course       = masteriyo_get_course( $this->get_course_id() );

		if ( $course ) {
			$course_preview_link = $course->get_preview_link( false );
			$preview_link        = trailingslashit( $course_preview_link ) . 'zoom/' . $this->get_id();
		}

		/**
		 * Zoom preview link for learn page.
		 *
		 * @since 2.5.19
		 *
		 * @param string $url Preview URL.
		 * @param \Masteriyo\Addons\Zoom\Models\Zoom $Zoom Zoom object.
		 */
		return apply_filters( 'masteriyo_zoom_preview_link', $preview_link, $this );
	}

	/**
	 * Get icon.
	 *
	 * @since 2.5.19
	 *
	 * @return string
	 */
	public function get_icon( $context = 'single-course.zoom.section.content' ) {
		$icon = masteriyo_get_svg( 'zoom' );

		/**
		 * Filters zoom icon.
		 *
		 * @since 2.5.19
		 *
		 * @param string $icon.
		 * @param string $context.
		 */
		return apply_filters( 'masteriyo_zoom_icon', $icon, $context );
	}

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

	/**
	 * Get Zoom session name.
	 *
	 * @since  2.5.19
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 *
	 * @return string
	 */
	public function get_name( $context = 'view' ) {
		/**
		 * Filters Zoom name.
		 *
		 * @since 2.5.19
		 *
		 * @param string $name Zoom name.
		 * @param \Masteriyo\Models\Zoom $Zoom Zoom object.
		 */
		return apply_filters( 'masteriyo_zoom_name', $this->get_prop( 'name', $context ), $this );
	}

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

	/**
	 * Get Zoom session created date.
	 *
	 * @since  2.5.19
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 *
	 * @return 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 Zoom mute upon entry.
	 *
	 * @since  2.5.19
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 *
	*/
	public function get_mute_upon_entry( $context = 'view' ) {
		return $this->get_prop( 'mute_upon_entry', $context );
	}

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

	/**
	 * Get Zoom session modified date.
	 *
	 * @since  2.5.19
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 *
	 * @return 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 );
	}

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

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

	/**
	 * Returns Zoom meeting id.
	 *
	 * @since  2.5.19
	 *
	 * @param  integer $context What the value is for. Valid values are view and edit.
	 *
	 * @return integer
	 */
	public function get_meeting_id( $context = 'view' ) {
		return $this->get_prop( 'meeting_id', $context );
	}

	/**
	 * Returns Zoom session menu order.
	 *
	 * @since  2.5.19
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 *
	 * @return string
	 */
	public function get_menu_order( $context = 'view' ) {
		return $this->get_prop( 'menu_order', $context );
	}

	/**
	 * Get Zoom session status.
	 *
	 * @since  2.5.19
	 *
	 * @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 Zoom session duration.
	 *
	 * @since  2.5.19
	 *
	 * @param  integer $context What the value is for. Valid values are view and edit.
	 *
	 * @return integer
	 */
	public function get_duration( $context = 'view' ) {
		return $this->get_prop( 'duration', $context );
	}

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

	/**
	 * Get Zoom session join before host.
	 *
	 * @since  2.5.19
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 *
	 * @return boolean
	 */
	public function get_join_before_host( $context = 'view' ) {
		return $this->get_prop( 'join_before_host', $context );
	}

	/**
	 * Get Zoom session get focus mode.
	 *
	 * @since  2.5.19
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 *
	 * @return boolean
	 */
	public function get_focus_mode( $context = 'view' ) {
		return $this->get_prop( 'focus_mode', $context );
	}

	/**
	 * Get Zoom session participant video setting.
	 *
	 * @since  2.5.19
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 *
	 * @return boolean
	 */
	public function get_participant_video( $context = 'view' ) {
		return $this->get_prop( 'participant_video', $context );
	}

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

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

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

	/**
	 * Get zoom session expires date in timestamp
	 *
	 * @since  2.5.19
	 *
	 * @param  integer $context What the value is for. Valid values are view and edit.
	 *
	 * @return DateTime|NULL object if the date is set or null if there is no date.
	 */
	public function get_expires_at( $context = 'view' ) {
		$result     = null;
		$expires_at = $this->data['expires_at'];

		if ( $this->get_duration() ) {
			$expires_at = $this->get_starts_at() ? $this->get_starts_at()->getTimestamp() + $this->get_duration() * MINUTE_IN_SECONDS : null;
		} else {
			$expires_at = $this->get_starts_at();
		}

		$this->set_expires_at( $expires_at );
		$expires_at = $this->get_prop( 'expires_at', $context );

		if ( masteriyo_rest_prepare_date_response( $expires_at ) ) {
			$result = 'view' === $context ? $expires_at : $expires_at->getTimestamp();
		}

		return $result;
	}

	/**
	 * Get zoom session starts date in timestamp
	 *
	 * @since  2.5.19
	 *
	 * @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_starts_at( $context = 'view' ) {
		$result    = null;
		$starts_at = $this->get_prop( 'starts_at', $context );

		if ( masteriyo_rest_prepare_date_response( $starts_at ) ) {
			$result = 'view' === $context ? $starts_at : $starts_at->getTimestamp();
		}

		return $result;
	}

	/**
	 * Get Zoom course id.
	 *
	 * @since  2.5.19
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 *
	 * @return integer
	 */
	public function get_course_id( $context = 'view' ) {
		return $this->get_prop( 'course_id', $context );
	}


	/**
	 * Get Zoom session close registration setting.
	 *
	 * @since  2.5.19
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 *
	 * @return boolean
	 */
	public function get_close_registration( $context = 'view' ) {
		return $this->get_prop( 'close_registration', $context );
	}

	/**
	 * Returns the Zoom author id.
	 *
	 * @since  2.5.19
	 *
	 * @param  string $context What the value is for. Valid values are view and edit.
	 *
	 * @return integer
	 */
	public function get_author_id( $context = 'view' ) {
		return $this->get_prop( 'author_id', $context );
	}

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

	/**
	 * Set Zoom name.
	 *
	 * @since 2.5.19
	 *
	 * @param string $name Zoom name.
	 */
	public function set_name( $name ) {
		$this->set_prop( 'name', $name );
	}

	/**
	 * Set the Zoom author id.
	 *
	 * @since 2.5.19
	 *
	 * @param int $author_id author id.
	 */
	public function set_author_id( $author_id ) {
		$this->set_prop( 'author_id', absint( $author_id ) );
	}

	/**
	 * Set Zoom timezone.
	 *
	 * @since 2.5.19
	 *
	 * @param string $time_zone Zoom.
	 */
	public function set_time_zone( $time_zone ) {
		$this->set_prop( 'time_zone', $time_zone );
	}

	/**
	 * Set Host video.
	 *
	 * @since 2.5.19
	 *
	 * @param boolean $host_video .
	 */
	public function set_host_video( $host_video ) {
		$this->set_prop( 'host_video', masteriyo_string_to_bool( $host_video ) );
	}

	/**
	 * Set Zoom session created date.
	 *
	 * @since 2.5.19
	 *
	 * @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 course id.
	 *
	 * @since 2.5.19
	 *
	 *  @param int $course_id course id.
	 */
	public function set_course_id( $course_id ) {
		$this->set_prop( 'course_id', absint( $course_id ) );
	}

	/**
	 * Set Zoom session modified date.
	 *
	 * @since 2.5.19
	 *
	 * @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 );
	}

	/**
	 * Set Zoom session descriptions.
	 *
	 * @since 2.5.19
	 *
	 * @param string $description Zoom description.
	 */
	public function set_description( $description ) {
		$this->set_prop( 'description', $description );
	}

	/**
	 * Set the Zoom session parent id.
	 *
	 * @since 2.5.19
	 *
	 * @param int $parent Parent id.
	 */
	public function set_parent_id( $parent ) {
		$this->set_prop( 'parent_id', absint( $parent ) );
	}

	/**
	 * Set the Zoom session meeting id.
	 *
	 * @since 2.5.19
	 *
	 * @param int $meeting meeting id.
	 */
	public function set_meeting_id( $meeting ) {
		$this->set_prop( 'meeting_id', $meeting );
	}

	/**
	 * Set the Zoom session menu order.
	 *
	 * @since 2.5.19
	 *
	 * @param int $menu_order Menu order id.
	 */
	public function set_menu_order( $menu_order ) {
		$this->set_prop( 'menu_order', absint( $menu_order ) );
	}

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

	/**
	 * Set Zoom password.
	 *
	 * @since 2.5.19
	 *
	 * @param string $password password.
	 */
	public function set_password( $password ) {
		$this->set_prop( 'password', $password );
	}

	/**
	 * Set Zoom session duration.
	 *
	 * @since 2.5.19
	 *
	 * @param string $duration Zoom duration.
	 */
	public function set_duration( $duration ) {
		$this->set_prop( 'duration', absint( $duration ) );
	}

	/**
	 * Set Zoom session start_url.
	 *
	 * @since 2.5.19
	 *
	 * @param string $start_url Zoom start_url.
	 */
	public function set_start_url( $start_url ) {
		$this->set_prop( 'start_url', $start_url );
	}

		/**
	 * Set Zoom session join_url.
	 *
	 * @since 2.5.19
	 *
	 * @param string $join_url Zoom join_url.
	 */
	public function set_join_url( $join_url ) {
		$this->set_prop( 'join_url', $join_url );
	}

	/**
	 * Set Zoom session join before host setting.
	 *
	 * @since 2.5.19
	 *
	 * @param boolean $join_before_host Zoom join before host.
	 */
	public function set_join_before_host( $join_before_host ) {
		$this->set_prop( 'join_before_host', masteriyo_string_to_bool( $join_before_host ) );
	}

	/**
	 * Set Zoom session focus mode.
	 *
	 * @since 2.5.19
	 *
	 * @param boolean $focus_mode Zoom focus mode.
	 */
	public function set_focus_mode( $focus_mode ) {
		$this->set_prop( 'focus_mode', masteriyo_string_to_bool( $focus_mode ) );
	}

	/**
	 * Set Zoom session type.
	 *
	 * @since 2.5.19
	 *
	 * @param string $type Zoom type.
	 */
	public function set_type( $type ) {
		$this->set_prop( 'type', $type );
	}

	/**
	 * Set Zoom mute upon entry setting.
	 *
	 * @since 2.5.19
	 *
	 * @param boolean $mute_upon_entry Zoom mute upon entry.
	 */
	public function set_mute_upon_entry( $mute_upon_entry ) {
		$this->set_prop( 'mute_upon_entry', masteriyo_string_to_bool( $mute_upon_entry ) );
	}

	/**
	 * Set Zoom participant video setting.
	 *
	 * @since 2.5.19
	 *
	 * @param boolean $participant_video Zoom participant_video.
	 */
	public function set_participant_video( $participant_video ) {
		$this->set_prop( 'participant_video', masteriyo_string_to_bool( $participant_video ) );
	}

	/**
	 * Set Zoom record setting.
	 *
	 * @since 2.5.19
	 *
	 * @param string $record Zoom record.
	 */
	public function set_record( $record ) {
		$this->set_prop( 'record', $record );
	}

	/**
	 * Set Zoom expiring time.
	 *
	 * @since 2.5.19
	 *
	 * @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_expires_at( $expires_at ) {
		$this->set_date_prop( 'expires_at', $expires_at );
	}

	/**
	 * Set Zoom start time.
	 *
	 * @since 2.5.19
	 *
	 * @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_starts_at( $starts_at ) {
		$this->set_date_prop( 'starts_at', $starts_at );
	}

	/**
	 * Set Zoom session close registration .
	 *
	 * @since 2.5.19
	 *
	 * @param boolean $set_close_registration Zoom set close registration.
	 */
	public function set_close_registration( $close_registration ) {
		$this->set_prop( 'close_registration', masteriyo_string_to_bool( $close_registration ) );
	}

	/**
	 * Get dynamic status of the Zoom Session.
	 *
	 * @since 2.5.19
	 *
	 * @return string
	 */
	public function get_dynamic_status() {
		$status = $this->get_status();
		if ( ZoomMeetingStatus::DRAFT === $status || ZoomMeetingStatus::TRASH === $status ) {
			$dynamic_status = $status;
		} elseif ( $this->is_expired() ) {
			$dynamic_status = ZoomMeetingStatus::EXPIRED;
		} elseif ( $this->is_upcoming() ) {
			$dynamic_status = ZoomMeetingStatus::UPCOMING;
		} elseif ( $this->is_active() ) {
			$dynamic_status = ZoomMeetingStatus::ACTIVE;
		} else {
			$dynamic_status = $status;
		}

		/**
		 * Filters meeting dynamic status.
		 *
		 * @since 2.5.19
		 *
		 * @param string $dynamic_status Dynamic status.
		 * @param string $status meeting status
		 * @param \Masteriyo\Addons\Zoom\Models\Zoom $this Zoom object.
		 */
		return apply_filters( 'masteriyo_zoom_dynamic_status', $dynamic_status, $status, $this );
	}

	/**
	 * Checks if the meeting has expired.
	 *
	 * @since 2.5.19
	 *
	 * @return boolean
	 */
	public function is_expired() {
		$expiry_date = $this->get_expires_at( 'edit' );
		$expired     = time() > $expiry_date ? true : false;

		/**
		 * Filters boolean: True if the meeting has expired, otherwise false.
		 *
		 * @since 2.5.19
		 *
		 * @param boolean $expired True if the meeting has expired, otherwise false.
		 * @param \Masteriyo\Addons\Zoom\Models\Zoom $zoom
		 */
		$expired = apply_filters( 'masteriyo_zoom_meeting_is_expired', $expired, $this );

		return masteriyo_string_to_bool( $expired );
	}


	/**
	 * Checks if the meeting is scheduled.
	 *
	 * @since 2.5.19
	 *
	 * @return boolean
	 */
	public function is_upcoming() {
		$starts_at = $this->get_starts_at( 'edit' );
		$upcoming  = time() < $starts_at ? true : false;

		/**
		 * Filters boolean: True if the meeting has upcoming, otherwise false.
		 *
		 * @since 2.5.19
		 *
		 * @param boolean $upcoming True if the meeting has upcoming, otherwise false.
		 * @param \Masteriyo\Addons\Zoom\Models\Zoom $zoom
		 */
		$upcoming = apply_filters( 'masteriyo_zoom_meeting_is_upcoming', $upcoming, $this );

		return masteriyo_string_to_bool( $upcoming );
	}

	/**
	 * Checks if the session is active.
	 *
	 * @since 2.5.19
	 *
	 * @return boolean
	 */
	public function is_active() {
		$starts_at    = $this->get_starts_at( 'edit' );
		$current_time = time();
		$expires_at   = $this->get_expires_at( 'edit' );

		$active = ( $current_time >= $starts_at && $current_time <= $expires_at ) ? true : false;

		/**
		 * Filters boolean: True if the session has active, otherwise false.
		 *
		 * @since 2.5.19
		 *
		 * @param boolean $active True if the session has active, otherwise false.
		 * @param \Masteriyo\Addons\Zoom\Models\Zoom $zoom
		 */
		$active = apply_filters( 'masteriyo_zoom_meeting_is_active', $active, $this );

		return masteriyo_string_to_bool( $active );
	}
}
