<?php
/**
 * @author : Jegtheme
 */

namespace JNEWS_VIDEO\Objects;

/**
 * Class History
 *
 * @package JNEWS_VIDEO\Object
 */
class History extends Object_Video {

	/**
	 * Instance of History
	 *
	 * @var History
	 */
	private static $instance;

	/**
	 * Save endpoint value
	 *
	 * @var array
	 */
	private static $endpoint;

	/**
	 * The user id
	 *
	 * @var int
	 */
	protected $user_id;

	/**
	 * The post id
	 *
	 * @var int
	 */
	protected $post_id;

	/**
	 * Current page slug
	 *
	 * @var string
	 */
	private $current_page;

	/**
	 * History constructor.
	 */
	protected function __construct() {
		$this->setup_init();
		$this->setup_endpoint();
	}

	/**
	 * Setup History init
	 */
	public function setup_init() {
		add_action( 'init', array( $this, 'setup_hook' ) );
		add_filter( 'template_include', array( $this, 'history_template' ) );
		add_action( 'template_redirect', array( $this, 'set_post_id' ) );
		add_action( 'wpmu_new_blog', array( $this, 'new_site_activation' ) );

		add_action( 'jnews_video_get_right_content', array( $this, 'get_right_content' ) );
		add_action( 'jnews_video_get_right_title', array( $this, 'get_right_title' ) );

		// Remove post/page prefetching!
		remove_action( 'wp_head', 'adjacent_posts_rel_link_wp_head' );

		add_action( 'wp_head', array( $this, 'first_load_action' ) );
		add_action( 'jnews_do_first_load_action', array( $this, 'video_history' ), null, 2 );
	}

	/**
	 * Setup History endpoint
	 */
	protected function setup_endpoint() {
		$endpoint = array(
			'history' => array(
				'slug'  => 'history',
				'label' => 'history',
				'title' => esc_html__( 'History', 'jnews-video' ),
			),
		);

		self::$endpoint = apply_filters( 'jnews_history_page_endpoint', $endpoint );
	}

	/**
	 * TODO: Implement plugin_activation() method.
	 */
	public static function plugin_activation() {
		if ( ! self::is_table_installed( self::get_table_name() ) ) {
			self::create_table();
		}
		self::flush_rewrite_rules();
	}

	/**
	 * TODO: Implement get_table_name() method.
	 *
	 * @return string
	 */
	public static function get_table_name() {
		global $wpdb;

		return $wpdb->prefix . JNEWS_VIDEO_STATISTICS_DB_DATA;
	}

	/**
	 * Create Required Table
	 * TODO: Implement create_table() method.
	 */
	public static function create_table() {
		global $wpdb;

		$charset_collate = $wpdb->get_charset_collate();

		$create_data_table = 'CREATE TABLE ' . self::get_table_name() . " (
			ID bigint(20) unsigned NOT NULL AUTO_INCREMENT,
			user_id bigint(20) unsigned NOT NULL,
			post_id bigint(20) unsigned NOT NULL,
			date datetime NOT NULL default '0000-00-00 00:00:00',
	        date_gmt datetime NOT NULL default '0000-00-00 00:00:00',
	        PRIMARY KEY (ID),
	        KEY user_id (user_id),
	        KEY index_ID ( user_id, post_id, ID ),
	        KEY index_post_id ( user_id, date_gmt, post_id )
  		) {$charset_collate};";

		require_once ABSPATH . 'wp-admin/includes/upgrade.php';
		dbDelta( $create_data_table );
	}

	/**
	 * Flush rewrite rules
	 */
	private static function flush_rewrite_rules() {
		self::add_rewrite_rule();

		global $wp_rewrite;
		$wp_rewrite->flush_rules();
	}

	/**
	 * Create new rewrite rule
	 */
	private static function add_rewrite_rule() {
		foreach ( self::$endpoint as $endpoint ) {
			add_rewrite_endpoint( $endpoint['slug'], EP_ROOT | EP_PAGES );
		}
	}

	/**
	 * Singleton page of History class
	 *
	 * @return History
	 */
	public static function get_instance() {
		if ( null === static::$instance ) {
			static::$instance = new static();
		}

		return static::$instance;
	}

	/**
	 * Get custom endpoint slug
	 *
	 * @param string $page Custom Endpoint slug.
	 *
	 * @return mixed
	 */
	public function get_slug( $page ) {
		foreach ( self::$endpoint as $key => $value ) {
			if ( $page === $key ) {
				return $value['slug'];
			}
		}
	}

	/**
	 * Override new site activation
	 *
	 * @param int $blog_id The ID of the blog.
	 */
	public function new_site_activation( $blog_id ) {
		return parent::new_site_activation( $blog_id ); // TODO: Change the autogenerated stub.
	}

	/**
	 * Setup History hook
	 */
	public function setup_hook() {
		self::flush_rewrite_rules();
	}

	/**
	 * Register history template file
	 *
	 * @param $template
	 *
	 * @return string
	 */
	public function history_template( $template ) {
		global $wp;

		if ( $this->is_history_page( $wp ) ) {
			$template = JNEWS_VIDEO_TEMPLATE . '/history/history.php';
		}

		return $template;
	}

	/**
	 * Check the history page
	 *
	 * @param $wp
	 *
	 * @return bool
	 */
	protected function is_history_page( $wp ) {
		$bool = false;
		if ( ! is_admin() ) {
			foreach ( self::$endpoint as $key => $value ) {
				if ( isset( $wp->query_vars[ $value['slug'] ] ) ) {
					$this->setup_current_page( $value['slug'] );
					$bool = true;
				}
			}
		}

		return $bool;
	}

	/**
	 * Set current page value
	 *
	 * @param $page
	 */
	protected function setup_current_page( $page ) {
		foreach ( self::$endpoint as $key => $value ) {
			if ( $page === $value['slug'] ) {
				$this->current_page = $key;
			}
		}
	}

	/**
	 * Get the right content
	 */
	public function get_right_content() {
		global $wp;

		if ( $this->is_history_page( $wp ) ) {
			if ( ! is_user_logged_in() ) {
				jnews_video_get_template_part( '/fragment/history/history', 'login' );
			} else {
				jnews_video_get_template_part( '/fragment/history/history', 'content' );
			}
		}
	}

	/**
	 * Get the right title
	 */
	public function get_right_title() {
		if ( isset( $this->current_page ) ) {
			echo jnews_return_translation( self::$endpoint[ $this->current_page ]['title'], 'jnews-video', self::$endpoint[ $this->current_page ]['label'] );
		}
	}

	/**
	 * Print Ajax Header
	 */
	public function first_load_action() {
		if ( is_user_logged_in() && 0 !== $this->getPost_id() && get_post_type( $this->getPost_id() ) === 'post' && $this->is_video( $this->getPost_id() ) ) {
			do_action( 'jnews_push_first_load_action', 'video_history' );
		}
	}

	/**
	 * Get Post id
	 *
	 * @return int
	 */
	public function getPost_id() {
		return $this->post_id;
	}

	/**
	 * Set post id
	 *
	 * @param $post_id
	 */
	public function setPost_id( $post_id ) {
		$this->post_id = $this->is_numeric( $post_id ) ? (int) $post_id : 0;
	}

	/**
	 * Set Post ID in Single
	 */
	public function set_post_id() {
		$trackable             = array();
		$registered_post_types = get_post_types( array( 'public' => true ), 'names' );

		foreach ( $registered_post_types as $post_type ) {
			$trackable[] = $post_type;
		}

		$trackable = apply_filters( 'jnews_trackable_post_types', $trackable );

		if ( is_singular( $trackable ) && ! is_front_page() && ! is_preview() && ! is_trackback() && ! is_feed() && ! is_robots() ) {
			global $post;
			if ( $this->is_video( $post->ID ) ) {
				$this->setPost_id( $post->ID );
				$this->setUser_id( get_current_user_id() );
			}
		} else {
			$this->setPost_id( 0 );
			$this->setUser_id( get_current_user_id() );
		}
	}

	/**
	 * Check if post is video
	 *
	 * @param $id
	 *
	 * @return bool
	 */
	private function is_video( $id ) {
		$post_format = get_post_format( $id );
		if ( 'video' === $post_format ) {
			return true;
		}

		return false;
	}

	/**
	 * Ajax video history
	 *
	 * @param $response
	 * @param $action
	 *
	 * @return mixed
	 */
	public function video_history( $response, $action ) {
		if ( in_array( 'video_history', $action ) && is_user_logged_in() ) {
			$this->setUser_id( get_current_user_id() );
			$response['video_history'] = $this->jnews_history_ajax();
		}

		return $response;
	}

	/**
	 * Ajax View
	 *
	 * @return string
	 */
	public function jnews_history_ajax() {
		if ( isset( $_POST['jnews_id'] ) && $this->is_numeric( $_POST['jnews_id'] ) ) {
			$post_ID = (int) sanitize_text_field( $_POST['jnews_id'] );

			$exec_time = 0;

			$start  = $this->microtime_float();
			$result = $this->update_history( $post_ID );
			$end    = $this->microtime_float();

			$exec_time += round( $end - $start, 6 );

			if ( $result ) {
				return ( 'JNews Video History: OK. Execution time: ' . $exec_time . ' seconds' );
			}
		}

		return ( 'JNews Video History: Oops, could not update the video history!' );
	}

	/**
	 * Checks for valid number
	 *
	 * @param int    number
	 *
	 * @return    bool
	 */
	private function is_numeric( $number ) {
		return ! empty( $number ) && is_numeric( $number ) && ( intval( $number ) == floatval( $number ) );
	}

	/**
	 * @return float
	 */
	private function microtime_float() {
		list( $msec, $sec ) = explode( ' ', microtime() );

		$microtime = (float) $msec + (float) $sec;

		return $microtime;
	}

	/**
	 * Update history table add new data
	 *
	 * @param $id
	 *
	 * @return bool
	 */
	private function update_history( $id ) {
		global $wpdb;
		$wpdb->show_errors();
		// WPML support, get original post/page ID.
		if ( defined( 'ICL_LANGUAGE_CODE' ) && function_exists( 'icl_object_id' ) ) {
			global $sitepress;
			if ( isset( $sitepress ) ) { // avoids a fatal error with Polylang.
				$id = icl_object_id( $id, get_post_type( $id ), true, $sitepress->get_default_language() );
			} elseif ( function_exists( 'pll_default_language' ) ) { // adds Polylang support.
				$id = icl_object_id( $id, get_post_type( $id ), true, pll_default_language() );
			}
		}
		$this->setPost_id( $id );

		$history = $this->in_history( $this->getPost_id(), $this->getUser_id() );
		if ( ! $history ) {
			$result = $wpdb->insert(
				self::get_table_name(),
				array(
					'post_id'  => $this->getPost_id(),
					'user_id'  => $this->getUser_id(),
					'date'     => $this->now(),
					'date_gmt' => $this->nowgmt(),
				),
				array(
					'%d',
					'%d',
					'%s',
					'%s',
				)
			);
		} else {
			$result = $this->update_exist_history( $history );
		}
		if ( ! $result ) {
			return false;
		}

		return true;
	}

	/**
	 * Check if video already in history
	 *
	 * @param $post_id
	 * @param $user_id
	 *
	 * @return bool|int
	 */
	public function in_history( $post_id, $user_id ) {
		global $wpdb;

		// Prepare to use in SQL.
		$post_id = (int) $post_id;
		$user_id = (int) $user_id;

		$id = $wpdb->get_var( $wpdb->prepare( 'SELECT ID FROM ' . self::get_table_name() . ' WHERE user_id = %d AND post_id = %d', $user_id, $post_id ) );

		if ( null !== $id ) {
			return (int) $id;
		}

		return false;
	}

	/**
	 * Get user id
	 *
	 * @return int
	 */
	public function getUser_id() {
		return $this->user_id;
	}

	/**
	 * Set user id
	 *
	 * @param $user_id
	 */
	public function setUser_id( $user_id ) {
		$this->user_id = $this->is_numeric( $user_id ) ? (int) $user_id : 0;
	}

	/**
	 *  Update if video has been watch to avoid multiple video watched
	 *
	 * @param $id
	 *
	 * @return bool
	 */
	private function update_exist_history( $id ) {
		global $wpdb;
		$wpdb->show_errors();

		$result = $wpdb->update(
			self::get_table_name(),
			array(
				'date'     => $this->now(),
				'date_gmt' => $this->nowgmt(),
			),
			array( 'id' => $id )
		);
		if ( ! $result ) {
			return false;
		}

		return true;
	}

	/**
	 * @param null $user_id
	 *
	 * @return array
	 */
	public function get_history_video( $user_id = null ) {
		if ( empty( $user_id ) ) {
			$user_id = get_current_user_id();
		}
		$post_ids = $this->get_posts( $user_id );
		$post_ids = ! empty( $post_ids ) ? $post_ids : array();

		return $post_ids;
	}

	/**
	 * Return list of post ids belong to the user
	 *
	 * @param int $user_id
	 *
	 * @return array
	 */
	protected function get_posts( $user_id = 0 ) {
		global $wpdb;

		$results = $wpdb->get_results(
			$wpdb->prepare(
				'SELECT post_id FROM ' . self::get_table_name() . ' WHERE user_id = %d ORDER BY date_gmt DESC',
				$user_id
			),
			ARRAY_A
		);

		$ids = array();

		if ( $results ) {
			foreach ( $results as $result ) {
				$ids[] = $result['post_id'];
			}
		}

		return $ids;
	}

}
