<?php
///////////////////////////////////////////////////////////////////////////

require_once 'lib/vod/vod.php';

abstract class AbstractVod implements Vod
{
	private $short_movie_by_id;
	private $movie_by_id;
	private $failed_movie_ids;
	private $favorites_supported;
	private $movie_page_supported;
	private $playback_url_is_stream_url;
	private $fav_movie_ids;
	private $fav_movie_ids_set;
	private $genres;

	protected function __construct(
		$favorites_supported,
		$movie_page_supported,
		$playback_url_is_stream_url)
	{
		$this->favorites_supported = $favorites_supported;
		$this->movie_page_supported = $movie_page_supported;
		$this->playback_url_is_stream_url = $playback_url_is_stream_url;
		$this->short_movie_by_id = array();
		$this->movie_by_id = array();
		$this->failed_movie_ids = array();
	}

	///////////////////////////////////////////////////////////////////////

	public function set_cached_short_movie(ShortMovie $short_movie)
	{
		$this->short_movie_by_id[$short_movie->id] = $short_movie;
	}

	public function set_cached_movie(Movie $movie)
	{
		$this->movie_by_id[$movie->id] = $movie;

		$this->set_cached_short_movie(
			new ShortMovie($movie->id, $movie->name, $movie->poster_url));
	}

	public function set_failed_movie_id($movie_id)
	{
		$this->failed_movie_ids[$movie_id] = true;
	}

	public function set_fav_movie_ids($fav_movie_ids)
	{
		$this->fav_movie_ids = $fav_movie_ids;
		$this->fav_movie_ids_set = array();
		foreach ($this->fav_movie_ids as $id)
			$this->fav_movie_ids_set[$id] = true;
	}

	///////////////////////////////////////////////////////////////////////

	public function is_favorites_supported()
	{
		return $this->favorites_supported;
	}

	public function is_movie_page_supported()
	{
		return $this->movie_page_supported;
	}

	///////////////////////////////////////////////////////////////////////

	public function is_failed_movie_id($movie_id)
	{
		return isset($this->failed_movie_ids[$movie_id]);
	}

	public function has_cached_movie($movie_id)
	{
		return isset($this->movie_by_id[$movie_id]);
	}

	public function get_cached_movie($movie_id)
	{
		return isset($this->movie_by_id[$movie_id]) ?
			$this->movie_by_id[$movie_id] : null;
	}

	public function has_cached_short_movie($movie_id)
	{
		return isset($this->short_movie_by_id[$movie_id]);
	}

	public function get_cached_short_movie($movie_id)
	{
		return isset($this->short_movie_by_id[$movie_id]) ?
			$this->short_movie_by_id[$movie_id] : null;
	}

	public function clear_movie_cache()
	{
		$this->short_movie_by_id = array();
		$this->movie_by_id = array();
		$this->failed_movie_ids = array();

		$this->fav_movie_ids = null;
		$this->fav_movie_ids_set = array();
	}

	public function clear_genre_cache()
	{
		$this->genres = null;
	}

	///////////////////////////////////////////////////////////////////////

	public function ensure_movie_loaded($movie_id, &$plugin_cookies)
	{	
		if (!isset($movie_id))
			throw new Exception('Movie ID is not set');
		if ($this->is_failed_movie_id($movie_id))
			return null;
		$movie = $this->get_cached_movie($movie_id);
		if ($movie === null)
			$this->try_load_movie($movie_id, $plugin_cookies);
	}

	public function get_loaded_movie($movie_id, &$plugin_cookies)
	{
		$this->ensure_movie_loaded($movie_id, $plugin_cookies);
		return $this->get_cached_movie($movie_id);
	}

	///////////////////////////////////////////////////////////////////////

	public function get_vod_info(MediaURL $media_url, &$plugin_cookies)
	{
		$movie = $this->get_loaded_movie($media_url->movie_id, $plugin_cookies);
		if ($movie === null)
			return null;
		$sel_id = isset($media_url->series_id) ?
			$media_url->series_id : null;

		return $movie->get_vod_info($sel_id, $this->get_buffering_ms());
	}

	///////////////////////////////////////////////////////////////////////

	public function get_buffering_ms()
	{
		return 3000;
	}

	///////////////////////////////////////////////////////////////////////

	// This method should be overridden if and only if the
	// $playback_url_is_stream_url is false.
	public function get_vod_stream_url($playback_url, &$plugin_cookies)
	{ throw new Exception('Not implemented.'); }

	///////////////////////////////////////////////////////////////////////
	// Favorites.

	// This function is responsible for the following:
	//  - $this->fav_movie_ids should be initialized with array of movie
	//  ids
	//  - each of these movie ids should have loaded ShortMovie in
	//  short_movie_by_id map.
	//  - exception should be thrown if error occured.
	protected function load_favorites(&$plugin_cookies)
	{ throw new Exception('Not implemented'); }

	// This function should throw an exception if failed.
	protected function do_add_favorite_movie($movie_id, &$plugin_cookies)
	{ /* nop */ }

	// This function should throw an exception if failed.
	protected function do_remove_favorite_movie($movie_id, &$plugin_cookies)
	{ /* nop */ }

	// This function should not fail.
	protected function do_save_favorite_movies(&$fav_movie_ids, &$plugin_cookies)
	{ /* nop */ }

	public function ensure_favorites_loaded(&$plugin_cookies)
	{
		if ($this->fav_movie_ids !== null)
			return;

		$this->load_favorites($plugin_cookies);

		if ($this->fav_movie_ids === null)
			throw new Exception('Illegal state: favorites not loaded.');
	}

	public function add_favorite_movie($movie_id, &$plugin_cookies)
	{
		if (isset($this->fav_movie_ids_set[$movie_id]))
			return false;
		$this->do_add_favorite_movie($movie_id, $plugin_cookies);
		array_unshift($this->fav_movie_ids, $movie_id);
		$this->fav_movie_ids_set[$movie_id] = true;
		$this->do_save_favorite_movies($this->fav_movie_ids, $plugin_cookies);
		return true;
	}

	public function remove_favorite_movie($movie_id, &$plugin_cookies)
	{
		if (!isset($this->fav_movie_ids_set[$movie_id]))
			return false;

		$this->do_remove_favorite_movie($movie_id, $plugin_cookies);
		$k = array_search($movie_id, $this->fav_movie_ids);
		if ($k !== false)
			unset ($this->fav_movie_ids[$k]);
		unset ($this->fav_movie_ids_set[$movie_id]);

		$this->do_save_favorite_movies($this->fav_movie_ids, $plugin_cookies);

		return true;
	}

	public function get_favorite_movie_ids()
	{
		return $this->fav_movie_ids;
	}

	public function is_favorite_movie_id($movie_id)
	{
		return isset($this->fav_movie_ids_set[$movie_id]);
	}

	///////////////////////////////////////////////////////////////////////
	// Genres.

	protected function load_genres(&$plugin_cookies)
	{ throw new Exception("Not implemented."); }

	public function get_genre_icon_url($genre_id)
	{ throw new Exception('Not implemented'); }

	public function get_genre_media_url_str($genre_id)
	{ throw new Exception('Not implemented'); }

	public function ensure_genres_loaded(&$plugin_cookies)
	{
		if ($this->genres !== null)
			return;

		$this->genres = $this->load_genres($plugin_cookies);

		if ($this->genres === null)
			throw new Exception('Invalid VOD genres loaded');
	}

	public function get_genre_ids()
	{
		if ($this->genres === null)
			throw new Exception('VOD genres not loaded');

		return array_keys($this->genres);
	}

	public function get_genre_caption($genre_id)
	{
		if ($this->genres === null)
			throw new Exception('VOD genres not loaded');

		return $this->genres[$genre_id];
	}

	///////////////////////////////////////////////////////////////////////
	// Search.

	public function get_search_media_url_str($pattern)
	{ throw new Exception('Not implemented'); }

	///////////////////////////////////////////////////////////////////////
	// Folder views.

	public function get_vod_list_folder_views(&$plugin_cookies)
	{ throw new Exception('Not implemented'); }

	public function get_vod_genres_folder_views()
	{ throw new Exception('Not implemented'); }

	///////////////////////////////////////////////////////////////////////
	// Archive.

	public function get_archive(MediaURL $media_url)
	{ return null; }

	///////////////////////////////////////////////////////////////////////
	// Hook.

	public function folder_entered(MediaURL $media_url, &$plugin_cookies)
	{ /* Nop */ }
}

///////////////////////////////////////////////////////////////////////////