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

require_once 'lib/abstract_gcomps_screen.php';
require_once 'lib/action_factory.php';
require_once 'lib/gcomps_factory.php';
require_once 'config.php';


class ProgramScreen extends AbstractGCompsScreen
{
	const ID = 'epg_event_screen';

	public static function get_media_url_str($channel_id, $day, $start_tm, $transmission)
	{
		return
			MediaURL::encode(array('screen_id' => self::ID, 'channel_id' => $channel_id, 'day' => $day, 'start_tm' => $start_tm, 'transmission'	=> $transmission))->get_raw_string();
	}

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

	public function __construct()
	{
		parent::__construct(self::ID);
		DefaultDunePlugin::create_screen($this);
	}

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

	private $curr_icon_sel;
	private $prev_icon_sel;
	private $cur_media_url;
	private $cur_channel_id;
	private $cur_day;
	private $cur_day_json;
	private $cur_program;
	private $cur_labels;
	private $cur_label_counts;
	private $cur_icons;

	public	$program_event_data;
	public	$program_event_tm;

	public function invalidate()
	{
		$this->cur_media_url = null;
	}

	private function ensure_state($media_url)
	{
		if (isset($this->cur_media_url) &&
			$this->cur_media_url->get_raw_string() == $media_url->get_raw_string())
		{
			return;
		}

		$this->cur_media_url = $media_url;
		$this->reload_cur_program();

		$this->curr_icon_sel = 0;
		$this->prev_icon_sel = 0;
	}

	private static function check_documentary_movie($desc)
	{
		if (preg_match('|^"[^"]*". Документальный фильм|', $desc, $matches))
			return $matches[1];
		return null;
	}

	private static function check_documentary_series($desc)
	{
		if (preg_match('|^"[^"]*". Документальный цикл|', $desc, $matches))
			return $matches[1];
		return null;
	}

	private function reload_day_json()
	{
		if ($this->program_event_tm == $this->cur_media_url->start_tm)
		{
			$cur_day[$this->program_event_tm] = $this->program_event_data;
			$this->cur_day_json = json_decode(json_encode($cur_day));
			return;
		}
	}

	private function reload_cur_program()
	{
		$this->cur_program = false;
		$this->cur_icons = null;

		$channel_id = $this->cur_media_url->channel_id;
		$day = $this->cur_media_url->day;

		$tm = microtime(true);

		if (!isset($this->cur_channel_id) || !isset($this->cur_day) ||
			$channel_id != $this->cur_channel_id || $day != $this->cur_day)
		{
			$this->reload_day_json();
		}
		if (!isset($this->cur_day_json))
			return;

		$programs = $this->cur_day_json;
		$start_tm = $this->cur_media_url->start_tm;

		if (!isset($programs->$start_tm))
		{
			hd_print("Program not found: ".
				"start $start_tm channel $channel_id day $day");
			return;
		}

		$this->cur_program = $programs->$start_tm;
		$p = $this->cur_program;
		$this->cur_labels = array();
		$this->cur_label_counts = array();
		$label_keys =
			array
			(
				'title', 'categories', 'sub-title', 'desc', 'desc-sub-title',
				'year', 'country', 'production', 'imdb_rating', 'rating_ru',
				'presenter', 'actor', 'director', 'writer', 'editor', 'composer',
			);

		foreach ($label_keys as $key)
		{
			self::parse_value($this->cur_labels,
				$this->cur_label_counts, $p, $key);
		}

		if (isset($this->cur_labels['circledesc']))
		{
			$this->cur_labels['desc-sub-title'] = $this->cur_labels['circledesc'];
			unset($this->cur_labels['circledesc']);
		}

		$cat = isset($p->main_category) ? strval($p->main_category) : '';
		$genre = $cat;
		$is_series = false;
		if ($cat == 'Сериал' || $cat == 'T/c')
		{
			$is_series = true;
			$genre = 'Телесериал';
		}
		else if ($cat == 'Фильм' || $cat == 'X/ф')
			$genre = 'Художественный фильм';
		else if ($cat == 'Д/ф')
			$genre = 'Документальный фильм';
		else if ($cat == 'Д/с')
			$genre = 'Документальный сериал';
		else if ($cat == 'М/ф')
			$genre = 'Мультфильм';
		else if ($cat == 'М/с')
			$genre = 'Мультсериал';

		if (isset($this->cur_labels['desc']))
		{
			$new_desc = self::check_documentary_movie(
				$this->cur_labels['desc']);
			if (isset($new_desc))
			{
				$genre = 'Документальный фильм';
				$this->cur_labels['desc'] = $new_desc;
			}
			else
			{
				$new_desc = self::check_documentary_series(
					$this->cur_labels['desc']);
				if (isset($new_desc))
				{
					$genre = 'Документальный сериал';
					$this->cur_labels['desc'] = $new_desc;
					$is_series = true;
				}
			}

			$desc = $this->cur_labels['desc'];
			$pos = strpos($desc, "Подробная информация.");
			if ($pos !== false)
			{
				$this->cur_labels['desc'] =
					trim(substr($desc, 0, $pos));
				$this->cur_labels['desc2'] =
					trim(substr($desc, $pos + strlen("Подробная информация.")));
			}
		}

		if (isset($this->cur_labels['desc']) && isset($this->cur_labels['desc-sub-title']) &&
			$this->cur_labels['desc'] == $this->cur_labels['desc-sub-title'])
		{
			unset($this->cur_labels['desc-sub-title']);
		}

		$this->cur_labels['genre'] = $genre;

		if ($is_series && isset($this->cur_labels['desc-sub-title']))
		{
			$this->cur_labels['seriesdesc'] = $this->cur_labels['desc-sub-title'];
			unset($this->cur_labels['desc-sub-title']);
		}

		if ($this->cur_media_url->transmission != '')
			$this->cur_labels['transmission'] = $this->cur_media_url->transmission;

		if (isset($p->icons) && (count($p->icons) > 0))
		{
			$icons = array_merge(
				array($p->main_icon), $p->icons);
		}
		else
			$icons = array($p->main_icon);

		$this->cur_icons = array();
		foreach ($icons as $url)
		{
			$sep = false === strpos($url, '?') ? '?' : '&';
			$new_url = "$url${sep}ext=.jpg";
			$this->cur_icons[] = $new_url;
		}

		$tm_diff = microtime(true) - $tm;
		hd_print("Program reloaded in ${tm_diff}s");
	}

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

	private static function do_key_to_label($key, $count)
	{
		switch ($key)
		{
			case "year":
				return 'Год:';
			case "country":
				return 'Страна:';
			case "categories":
				return 'Жанр:';
			case "transmission":
				return 'Трансляция:';
			case "actor":
				return
					'В ролях:';
			case "presenter":
				return $count > 1 ? 'Ведущие:' : 'Ведущий:';
			case "director":
				return $count > 1 ?
					'Режиссеры:' : 'Режиссер:';
			case "editor":
				return $count > 1 ?
					'Операторы:' : 'Оператор:';
			case "composer":
				return $count > 1 ?
					'Композиторы:' : 'Композитор:';
			case "writer":
				return 'Сценарий:';
			case "production":
				return 'Производство:';
			case "seriesdesc":
				return 'О сериале:';
			case "desc-sub-title":
				return 'О передаче:';
			default:
				return null;
		}
	}

	private static function key_to_label($key, $count)
	{
		if ($key == "imdb_rating")
			return array("gui_skin://special_icons/imdb.png", true);

		$str = self::do_key_to_label($key, $count);
		if (!$str)
			$str = "empty://$key";
		return array($str, false);
	}

	private function do_add_labels(&$defs, $x, $y, $width, $keys)
	{
		$first = true;

		foreach ($keys as $key)
		{
			$value = isset($this->cur_labels[$key])? $this->cur_labels[$key] : null;

			if (empty($value))
				continue;

			switch ($key)
			{
				case 'title':
					$text_size = 60;
					$text_color = '#FFFFFFE0';
					$margins = GCompMargins::top(10);
					break;

				case 'sub-title':
					$text_size = 42;
					$text_color = '#FFFFFFE0';
					$margins = GCompMargins::top(-15);
					break;

				case 'genre':
					$text_size = 36;
					$text_color = '#FF808080';
					$margins = GCompMargins::all(0, -5, 0, 10);
					break;

				case 'desc2':
				case 'desc':
				case 'desc-sub-title':
				case 'seriesdesc':
				case 'production':
					$text_size = 36;
					$text_color = '#FFFFFFE0';
					$margins = GCompMargins::top(10);
					break;

				default:
					$text_size = 36;
					$text_color = '#FFFFFFE0';
					$margins = null;
			}

			$next_line = ($key == 'desc-sub-title' || $key == 'seriesdesc');
			$count = isset($this->cur_label_counts[$key])? $this->cur_label_counts[$key] : 1;

			list($label, $is_icon) = $this->key_to_label($key, $count);

			$geom = GCompGeom::top();

			if (0 === strpos($label, "empty://"))
				$label_def = null;
			else if ($is_icon)
				$label_def = GCompsFactory::get_image_def($geom, GCompMargins::all(0, 19, 12, 0), $label, true, true);
			else
				$label_def = GCompsFactory::label($geom, $next_line ? null : GCompMargins::right(20), $label, 1, "#FFAFAFA0", $text_size);

			$sub_defs = array();

			if (isset($label_def))
			{
				$geom = $next_line ?
					GCompGeom::place_top_left($width, -1) :
					GCompGeom::left();
				$sub_defs[] = GCompsFactory::get_panel_def(null,
					$geom, null, array($label_def));
			}

			$geom = $next_line && isset($label_def) ?
				GCompGeom::place_below_left($width, -1, 0, -22) :
				GCompGeom::center();
			$sub_defs[] = GCompsFactory::label($geom,
				null, $value, 0, $text_color, $text_size, null, array('line_spacing' => 4));

			if ($first)
				$geom = GCompGeom::place_top_left($width, -1, $x, $y);
			else
			{
				$geom = GCompGeom::place_below_left(
					$width, -1, 0, -17);
			}
			$defs[] = GCompsFactory::get_panel_def(null,
				$geom, $margins, $sub_defs);

			$first = false;
		}
	}

	private static function parse_value(&$labels, &$label_counts, $p, $key)
	{
		if (!isset($p->$key))
			return;

		if (is_string($p->$key) || is_integer($p->$key))
		{
			$labels[$key] = strval($p->$key);
			return;
		}

		if (is_array($p->$key))
		{
			$count = count($p->$key);
			if ($count == 0)
				return;

			if ($count != 1)
				$label_counts[$key] = $count;
			$labels[$key] = implode(", ", $p->$key);
		}
	}

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

	private function do_get_top_panel_def()
	{
		$defs = array();
		$line_spacing = array('line_spacing' => 3);

		if (!empty($this->cur_labels['title']))
		{
			$label_def = GCompsFactory::label(GCompGeom::top(TopPanelParams::width, -1), null, $this->cur_labels['title'], 2, TopPanelParams::title_font_color, TopPanelParams::title_font_size, null, $line_spacing);
			$defs[] = GCompsFactory::get_panel_def(null, GCompGeom::place_top_left(TopPanelParams::width - 250, -1, 0, -40), null, array($label_def));
		}

		if (!empty($this->cur_labels['sub-title']))
		{
			$label_def = GCompsFactory::label(GCompGeom::top(TopPanelParams::width, -1), null, $this->cur_labels['sub-title'], 1, TopPanelParams::sub_title_font_color, TopPanelParams::sub_title_font_size, null, $line_spacing);
			$defs[] = GCompsFactory::get_panel_def(null, GCompGeom::place_below_left(TopPanelParams::width - 250, -1, 0, -36), null, array($label_def));
		}

		$pane_def = GCompsFactory::get_panel_def(TopPanelParams::id, GCompGeom::place_bottom_left(TopPanelParams::width, TopPanelParams::height, 0, -10), null, $defs);

		return
			GCompsFactory::get_panel_def(TopPanelParams::id, GCompGeom::place_top_left(TopPanelParams::width, TopPanelParams::height, TopPanelParams::x, TopPanelParams::y), null, array($pane_def));
	}

	private function do_get_poster_defs($sel_state)
	{
		$defs = array();

		if (count($this->cur_icons) > 0)
			$defs[] = GCompsFactory::get_image_def(GCompGeom::place_top_left(LeftPanelParams::poster_width, LeftPanelParams::poster_height), null, $this->cur_icons[$sel_state->curr_icon_sel]);

		return $defs;
	}

	private function do_get_thumbnails_defs($sel_state)
	{
		$defs = array();
		$num_icons = max(0, min(16, count($this->cur_icons)));

		if ($num_icons > 0)
		{
			$x = round((LeftPanelParams::width - $num_icons * 32) / 2);

			for ($icon_ndx = 0; $icon_ndx < $num_icons; $icon_ndx++)
				$defs[] = GCompsFactory::get_image_def(
					GCompGeom::place_top_left(LeftPanelParams::thumbnail_width, LeftPanelParams::thumbnail_height, $x + 32*$icon_ndx, 0), null,
					'plugin_file://addons/ext_epg/icons/radio-button-' . (($sel_state->curr_icon_sel == $icon_ndx)? 'on' : 'off') . '.png');
		}

		return $defs;
	}

	private function do_get_left_panel_def($sel_state)
	{
		$defs = array();

		if (count($this->cur_icons) > 0)
		{
			$defs[] = GCompsFactory::get_panel_def(LeftPanelParams::poster_pane_id, GCompGeom::place_top_left(LeftPanelParams::poster_width, LeftPanelParams::poster_height), null, $this->do_get_poster_defs($sel_state));

			if (count($this->cur_icons) > 1)
			{
				$thumbnails_defs = $this->do_get_thumbnails_defs($sel_state);
				$defs[] = GCompsFactory::get_panel_def(LeftPanelParams::thumbnails_pane_id, GCompGeom::place_below_left(LeftPanelParams::poster_width, LeftPanelParams::thumbnail_height, 0, 12), null, $thumbnails_defs);
			}
		}

		return
			GCompsFactory::get_panel_def(null, GCompGeom::place_top_left(LeftPanelParams::width, LeftPanelParams::height, LeftPanelParams::x, LeftPanelParams::y), null, $defs);
	}

	private function do_get_right_panel_def()
	{
		$defs = array();

		$right_label_keys =
			array
			(
				"imdb_rating",
				"year", "country", "presenter", "actor", "director",
				"editor", "writer", "composer", "desc", "desc2",
				"desc-sub-title", 'seriesdesc', "production",
			);

		$right_w = 1920 - 65 - 65 - 600 - 30;//L::$WIDTH - L::$SCREEN_LEFT - L::$SCREEN_RIGHT - L::$EPG_IMAGE_WIDTH - 30;
		self::do_add_labels($defs, 0, -20, $right_w, $right_label_keys);

		$x = 30 + 600 + 30;//L::$SCREEN_LEFT + L::$EPG_IMAGE_WIDTH + 30;
		$w = 1920 - 30 - 30 - $x;//L::$WIDTH - L::$SCREEN_RIGHT - $x;
		$h = 1080 - 30 - 190 - 338;//L::$HEIGHT - L::$VOD_PANEL_TOP - L::$VOD_PANEL_BOTTOM - L::$EPG_BOTTOM;
		$r = array($w, $h, $x, 30 + 190);//L::$VOD_PANEL_TOP);

		$geom = GCompGeom::place_top_left($r[0], $r[1], 0, 0);
		$spane_def = GCompsFactory::get_vertical_spane_def('right_spane', $geom, null, $defs);
		$scrollbar_def = GCompsFactory::get_scrollbar_def(GCompGeom::place_next_right_same_height(-1, -1, 20), null, 'right_spane');

		$geom = GCompGeom::place_top_left($r[0] + 30, $r[1], $r[2], $r[3]);

		return
			GCompsFactory::get_panel_def("right_panel", $geom, null, array($spane_def, $scrollbar_def));
	}

	private function do_get_hints_panel($cur_icon_sel_state)
	{
		$defs[] = GCompsFactory::get_image_def(GCompGeom::place_top_left(-1, 50), null, "plugin_file://addons/ext_epg/icons/p_plus_p_minus.png");
		$defs[] = GCompsFactory::label(
			GCompGeom::place_next_right_align_top(
				-1, 50,//L::$VOD_BUTTON_HEIGHT,
				0, 8),//-L::$COLOR_ICON_TEXT_DY),
			GCompMargins::all(5, 0 , 40, 0), 'Прокрутка', 1, "#FFAFAFA0", 36);//L::$TEXT_SIZE);//, null, array('line_spacing' => 3));

		$h = 50 + 8;//L::$VOD_BUTTON_HEIGHT + L::$COLOR_ICON_TEXT_DY;
		$x = 65 + 600 + 30;//L::$SCREEN_LEFT + L::$EPG_IMAGE_WIDTH + 30;
		$y = 1080 - 50 - 50 + 15;//L::$HEIGHT - L::$VOD_PANEL_BOTTOM - L::$VOD_BACK_ARROW_SIZE + 15;
		$geom = GCompGeom::place_top_left(-1, $h, $x, $y);

		return
			GCompsFactory::get_panel_def("hints_pane", $geom, null, $defs);
	}

	private function do_get_bottom_panel_def()
	{
		$defs = array();
		$line_spacing = array('line_spacing' => 4);
		$defs[] = GCompsFactory::get_image_def(GCompGeom::place_top_left(BottomPanelParams::width, 55, 0, 0), null, 'plugin_file://addons/ext_epg/icons/osd_glass_top.png');
		$defs[] = GCompsFactory::get_rect_def(GCompGeom::place_top_left(BottomPanelParams::width, BottomPanelParams::height, 0, 55), null, '#99000000');

		return
			GCompsFactory::get_panel_def(null, GCompGeom::place_top_left(BottomPanelParams::width, BottomPanelParams::height, BottomPanelParams::x, BottomPanelParams::y), null, $defs);
	}

	public function get_window_def(MediaURL $media_url, &$plugin_cookies)
	{
		$this->ensure_state($media_url);

		$sel_state = $this->get_selection_state();

		$defs = array();

		if ($this->cur_program === false)
			return
				GCompsFactory::get_window_def($defs, null, null, '#101010', null, false, 180);

		$defs[] = $this->do_get_top_panel_def();
		$defs[] = $this->do_get_left_panel_def($sel_state);
		$defs[] = $this->do_get_right_panel_def();
		$defs[] = $this->do_get_bottom_panel_def();

		return
			GCompsFactory::get_window_def($defs, null, null, '#101010', null, false, 180);
	}

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

	public function get_action_map(MediaURL $media_url, &$plugin_cookies)
	{
		$key_up_action = UserInputHandlerRegistry::create_action($this, GUI_EVENT_KEY_UP);
		$key_down_action = UserInputHandlerRegistry::create_action($this, GUI_EVENT_KEY_DOWN);

		return
			array
			(
				GUI_EVENT_KEY_ENTER => UserInputHandlerRegistry::create_action($this, GUI_EVENT_KEY_ENTER),
				GUI_EVENT_KEY_LEFT => UserInputHandlerRegistry::create_action($this, GUI_EVENT_KEY_LEFT),
				GUI_EVENT_KEY_RIGHT => UserInputHandlerRegistry::create_action($this, GUI_EVENT_KEY_RIGHT),
				GUI_EVENT_KEY_P_PLUS => UserInputHandlerRegistry::create_action($this, GUI_EVENT_KEY_P_PLUS),
				GUI_EVENT_KEY_P_MINUS => UserInputHandlerRegistry::create_action($this, GUI_EVENT_KEY_P_MINUS),
				GUI_EVENT_KEY_UP => $key_up_action,
				GUI_EVENT_KEY_DOWN => $key_down_action,
				GUI_EVENT_KEY_FIP_PREV => $key_up_action,
				GUI_EVENT_KEY_FIP_NEXT => $key_down_action,
				GUI_EVENT_KEY_INFO => ActionFactory::close_and_run(),
			);
	}

	private static function do_get_selection_state($curr_icon_sel, $prev_icon_sel)
	{
		return (object) array(
			'curr_icon_sel' => $curr_icon_sel,
			'prev_icon_sel' => $prev_icon_sel,
		);
	}

	private function get_selection_state()
	{
		return self::do_get_selection_state(
			$this->curr_icon_sel, $this->prev_icon_sel);
	}

	public function handle_user_input(&$user_input, &$plugin_cookies)
	{
		if (!isset($user_input->control_id))
			return null;

		$cur_icon_sel = $this->curr_icon_sel;
		$prev_icon_sel = $cur_icon_sel;
		$new_icon_sel = $cur_icon_sel;
		$y_offset = 0;

		switch ($user_input->control_id)
		{
			case GUI_EVENT_KEY_RIGHT:
				$new_icon_sel = min(max(1, count($this->cur_icons)) - 1, $cur_icon_sel + 1);
				break;

			case GUI_EVENT_KEY_LEFT:
				if (empty($prev_icon_sel))
					return ActionFactory::close_and_run();

				$new_icon_sel = max(0, $cur_icon_sel - 1);
				break;

			case GUI_EVENT_KEY_UP:
				$y_offset -= 100;
				break;

			case GUI_EVENT_KEY_DOWN:
				$y_offset += 100;
				break;

			case GUI_EVENT_KEY_P_PLUS:
				$y_offset = -500;//L::$VOD_SCROLL_SIZE;
				break;

			case GUI_EVENT_KEY_P_MINUS:
				$y_offset = 500;//L::$VOD_SCROLL_SIZE;
		}

		if ($y_offset != 0)
			$change_defs[] = GCompsFactory::get_change_def('right_spane', null, null, GCompsFactory::get_view_position_def(0, $y_offset));

		$new_sel_state = self::do_get_selection_state($new_icon_sel, $prev_icon_sel);

		if ($new_icon_sel != $cur_icon_sel)
		{
			$change_defs[] = GCompsFactory::get_change_def(LeftPanelParams::thumbnails_pane_id, null, null, null, null, $this->do_get_thumbnails_defs($new_sel_state), GCOMP_TRANSITION_DEFAULT);
			$change_defs[] = GCompsFactory::get_change_def(LeftPanelParams::poster_pane_id, null, null, null, null, $this->do_get_poster_defs($new_sel_state), GCOMP_TRANSITION_FADE);
		}

		$this->curr_icon_sel = $new_icon_sel;

		if (!isset($change_defs))
			return null;

		return
			ActionFactory::change_gcomps($this, $change_defs, false, 8);
	}
}

///////////////////////////////////////////////////////////////////////////
?>
