<?php

// Wink helper /////////////////////////////////////////////////////////////////

function Wink()
{
	static $wink;

	if (empty($wink))
		$wink = new Wink();

	return $wink;
}

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

final class Wink
{
	private		$api_base_url;
	private		$api_img_base_url;
	private		$api_fingerprint;
	private 	$api_client_ip;
	private		$api_session_id;
	private		$api_cur_mrf;
	private		$api_home_mrf;
	private		$api_cur_location;
	private		$api_home_location;
	private		$api_cur_sub_location;
	private		$api_home_sub_location;
	private		$api_cur_timezone_offset;
	private   	$cur_mrf;
	private		$cur_location_id;
	private		$cur_sub_location_id;
	private		$_force_update_cache;
	private		$_locations;
	private		$_packages;
	private		$_tv_channels;
	private     $_tv_groups;

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

	private static function sort_channels($a, $b)
	{
		$result = strcmp($a['id'], $b['id']);

		if (empty($result))
			$result = strnatcasecmp($a['number'], $b['number']);

		return
			empty($result)? strnatcasecmp(mb_strtolower($a['title'], 'UTF-8'), mb_strtolower($b['title'], 'UTF-8')) : $result;
	}

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

	private function bootstrap()
	{
		$path = get_paved_path(WINK_CACHE_STORAGE_PATH . "/api");
		$file = Cache::get_latest_file($path);

		if (empty($file) || (time() - $file > 43200))
			if ($page = http_get_document('https://wink.ru/', array(CURLOPT_HTTPHEADER => array('Accept: text/html'))))
			{
				$file = strval(time());

				if (@file_put_contents("$path/$file", $page))
					Cache::clean_dir($path, $file);
			}

		if (file_exists("$path/$file"))
			$page = file_get_contents("$path/$file");

		if (!$page)
			return false;

		if (preg_match('/,session_id:"(.*)",session_state:"demo"/Um', $page, $matches))
			$this->api_session_id = $matches[1];

		if (preg_match('/fingerprint:"(.+)"/Um', $page, $matches))
			$this->api_fingerprint = $matches[1];

		if (preg_match('/window.__DATA__=.+balancer.+api_url:"(.+)"/Um', $page, $matches))
			$this->api_base_url = rtrim($matches[1], '/');

		$post_fields =
			array
			(
				'device' =>
					array
					(
						'type' => 'NCWEB',
						'platform' => 'browser',
					),
				'fingerprint' => $this->api_fingerprint,
			);

		if ($response = $this->api_request('POST', '/api/v3/itv/sessions', array(CURLOPT_POSTFIELDS => json_encode($post_fields))))
		{
			$this->api_session_id = $response->session_id;
			$this->api_fingerprint = $response->fingerprint;
		}
		else if (empty($this->api_session_id))
			return false;

		if (preg_match('/window.__IMAGES_URL__="(.+)"/Um', $page, $matches))
			$img_base_url = rtrim($matches[1], '/');

		if (empty($img_base_url) && preg_match('/window.__DATA__.+img_url:"(.+)"/Um', $page, $matches))
			$this->api_img_base_url = rtrim($matches[1], '/');
		else
			$this->api_img_base_url = $img_base_url;

		if (preg_match('/user:.+client_ip:"(.+)"/Um', $page, $matches))
			$this->api_client_ip = $matches[1];

		if (preg_match('/current_timezone:.+offset_sec:((-|)\d+),/Um', $page, $matches))
			$this->api_cur_timezone_offset = $matches[1];

		if (preg_match('/,location:(\d+),/Um', $page, $matches))
			$this->api_home_location = $matches[1];

		if (preg_match('/,sub_location:(\d+),/Um', $page, $matches))
			$this->api_home_sub_location = $matches[1];

		if (preg_match('/,home_mrf:"(.+)"/Um', $page, $matches))
			$this->api_home_mrf = $matches[1];

		if (preg_match('/,cur_location:(\d+),/Um', $page, $matches))
			$this->api_cur_location = $matches[1];

		if (preg_match('/,cur_sub_location:(\d+),/Um', $page, $matches))
			$this->api_cur_sub_location = $matches[1];

		if (preg_match('/,current_mrf:"(.+)"/Um', $page, $matches))
			$this->api_cur_mrf = $matches[1];

		return
			!(empty($this->api_session_id) ||
				empty($this->api_fingerprint) ||
				empty($this->api_base_url));
	}

	private function xml_request($url)
	{
		$silent = defined('DEBUG_MODE_ON')? !DEBUG_MODE_ON : true;

		try
		{
			$t = microtime(true);

			if (preg_match('/^http(s|):\/\//', $url))
				$response = http_get_document($url, null, $silent);
			else
				$response = file_get_contents($url);
		}
		catch (Exception $e)
		{
			hd_print('Warning! Can\'t load data from ' . $url);
			hd_print($e);

			return false;
		}

		if (empty($response))
			return false;

		$json = json_decode(str_replace('{}', '""', json_encode(parse_xml_document($response))));

		if (!$silent)
			hd_print('Data successfully loaded in ' . round(microtime(true) - $t, 4) . ' sec');

		return $json;
	}

	private function api_request($method, $url, $opts = null, $silent = true)
	{
		if (empty($this->api_session_id))
			if (!$this->bootstrap())
				return false;

		$is_silent = defined('DEBUG_MODE_ON')? !DEBUG_MODE_ON : $silent;
		$url = preg_match('/http(s|):\/\//', $url)? $url : $this->api_base_url . $url;

		if (empty($opts))
			$opts = array();

		$opts +=
			array
			(
				CURLOPT_CUSTOMREQUEST => $method,
				CURLOPT_HTTPHEADER => array("session_id: {$this->api_session_id}"),
				CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36',
			);

		if (!$response = http_get_document($url, $opts, $is_silent))
			return null;

		$json = json_decode($response);

		if (isset($json->error_code))
		{
			hd_print(get_class($this) . rtrim(" Fatal error! Code: {$json->error_code}. {$json->description}" . (empty($json->debug_message)? '' : " ({$json->debug_message})")));
			return false;
		}
		else if (isset($json->message))
		{
			hd_print(get_class($this) . rtrim(" Warning! {$json->message}"));
			return false;
		}

		return $json;
	}

	private function load_locations_list()
	{
		hd_print('Start loading locations list...');

		if (empty($this->cur_location_id))
		{
			hd_print('Abort! Selected location is empty!');
			return 0;
		}

		$path = get_paved_path(WINK_CACHE_STORAGE_PATH . "/locations");
		$file = Cache::get_latest_file($path);

		if (empty($file) || ($this->_force_update_cache && (time() - $file > 86400)))
		{
			if (empty($file))
				hd_print('Cache is empty! Updating...');
			else
				hd_print('Cache is outdated! Updating...');

			try
			{
				$xml = http_get_document((defined('DEBUG_MODE_ON') && file_exists('/D/ncdxml/locations_list.xml'))? '/D/ncdxml/locations_list.xml' : decode_str('dSaHR0cHM6Ly9icmlnYWRpci5teWR1bmUucnUvaG9tZV90di93aW5rL2xvY2F0aW9uc19saXN0LnhtbA'), null, SILENT_HTTP_REQUESTS);

				if (empty($xml))
					throw new Exception();
			}
			catch (Exception $e)
			{
				hd_print('Warning! Could not load from a remote source, loading from a local.');
				$result = empty($file)? array() : unserialize(@file_get_contents("$path/$file"));

				if (empty($result))
					throw new Exception(get_class($this) . ': Locations list is crashed!');
			}

			if (!empty($xml))
				if ($xml = parse_xml_document($xml))
				{
					foreach($xml->{'location'} as $location)
					{
						$loc_id = strval($location->id);
						$result[$loc_id]['name'] = strval($location->name);
						$result[$loc_id]['mrf'] = strval($location->mrf);

						foreach ($location->{'sub'}->{'location'} as $sub_location)
						{
							$sub_id = strval($sub_location->id);
							$result[$loc_id]['sub'][$sub_id] =
								array
								(
									'yid' => strval($sub_location->yid),
									'name' => strval($sub_location->name),
									'timezone' => strval($sub_location->timezone),
									'offset_sec' => strval($sub_location->offset_sec),
								);
						}
					}

					$file = strval(time());

					if (@file_put_contents("$path/$file", serialize($result)))
					{
						Cache::clean_dir($path, $file);
						hd_print('Saved in the cache successfully!');
					}
					else
					{
						$file = false;
						hd_print('Error: failed to save in the cache!');
					}
				}
		}
		else
		{
			hd_print("Loading from the local cache \"$file\"");
			$result = unserialize(@file_get_contents("$path/$file"));
		}

		$this->_locations = $result;
	}

	private function get_icon_url($fname)
	{
		if (empty($fname))
			return '';

		return
			sprintf((defined('DEBUG_MODE_ON') && file_exists('/D/ncdxml/images'))? '/D/ncdxml/images/%s' : decode_str('VnaHR0cHM6Ly9icmlnYWRpci5teWR1bmUucnUvaG9tZV90di93aW5rL2ltYWdlcy8lcw'), $fname);
	}

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

	public function __construct()
	{
		$cache_storage_path = defined('LOCAL_CACHE_PATH')? LOCAL_CACHE_PATH : dirname(__FILE__) . '/cache';

		define('WINK_CACHE_STORAGE_PATH',	rtrim($cache_storage_path, '/') . '/wink');

		$this->cur_mrf = 'mos';
		$this->cur_location_id = 700001;
		$this->cur_sub_location_id = 700001;
		$this->_packages = array();
	}

	public function load_tv_channels($package)
	{
		$url = sprintf((defined('DEBUG_MODE_ON') && file_exists('/D/ncdxml/'))? '/D/ncdxml/list_channels_%s.xml' : decode_str('5yaHR0cHM6Ly9icmlnYWRpci5teWR1bmUucnUvaG9tZV90di93aW5rL2xpc3RfY2hhbm5lbHNfJXMueG1s'), $package);

		if (!$data = $this->xml_request($url))
			return false;

		if ($this->cur_sub_location_id == $this->cur_location_id)
		{
			if ($enabled_locations = $this->get_locations_list($this->cur_sub_location_id))
				if (is_array($enabled_locations))
					$enabled_locations = array_keys($enabled_locations);
		}
		else
			$enabled_locations = array($this->cur_sub_location_id);

		$c = empty($this->_tv_channels)? 0 : count(array_unique($this->_tv_channels['numbers']));
		$channels = isset($data->channels->channel)? (is_array($data->channels->channel)? $data->channels->channel : array($data->channels->channel)) : array();

		foreach ($channels as $channel)
		{
			$bcid = 0;
			$iteration = 0;
			$ott_url = '';
			$quality = '';
			$groups = array();
			$epg = array();
			$npvr_id = $channel->npvrId;
			$num = $channel->number;
			$bcname = ucwords(trim($channel->bcName));
			$title = trim(preg_replace(array('/\s+and\s+/i', '/^(\D{4,})-(\d+)$/u', '/\s{2,}/', '/Общественное\s+телевидение\s+России/ui', '/^Телеканал\s+«(.+)»\s*$/ui', '/^Телеканал\s+(известия)/ui', '/^Детско(\s*-\s*)юношеский телеканал\s+/ui', '/^Телекомпания\s+/ui', '/\s+(HD|4K)$/ui'), array(' & ', '$1 $2', ' ', 'ОТР', '$1', '$1', ''), $bcname));
			$title_id = get_canonize_string(preg_replace(array('/\s+Ultra$/', '/(-|\s+)ТВ$/ui', '/-|–/', '/\s/', '/!+$/'), '', $title));

			if (($num < 1) || ($num > 999) || ($num == 100))
				continue;

			if (!empty($channel->genres))
			{
				$channel_groups = is_array($channel->groups->group)? $channel->groups->group : array($channel->groups->group);

				foreach ($channel_groups as $group)
				{
					$this->_tv_groups[$group->id]['name'] = $group->name;
					$this->_tv_groups[$group->id]['logo'] = $this->get_icon_url("groups/{$group->logo}");
					$this->_tv_groups[$group->id]['logo_hash'] = $group->logo_hash;
					$groups[] = $group->id;
				}
			}

			$bcname = preg_replace(array('/-/', '/\s+/'), ' ', $bcname);
			$sd_name_sign = preg_match('/\s+(SD)(\s+.*|)$/ui', $bcname);
			$uhd_name_sign = !$sd_name_sign && preg_match('/\s+(4K|UHD|Ultra)(\s+.*|)$/ui', $bcname);
			$hd_name_sign = !$uhd_name_sign && preg_match('/\s+HD(\s+.*|)$/ui', $bcname);

			while($iteration < 2)
			{
				if (empty($iteration))
				{
					if (!empty($channel->locations))
					{
						$channel_locations = is_array($channel->locations->location)? $channel->locations->location : array($channel->locations->location);

						foreach ($channel_locations as $location)
						{
							$location_id = trim($location->id);

							if (in_array($location_id, $enabled_locations))
							{
								$ott_url = empty($location->ottURL)? '' : trim($location->ottURL);

								if (empty($ott_url))
									break;

								$epg = empty($location->epg->id)? array() : (is_array($location->epg->id)? $location->epg->id : array($location->epg->id));
								$quality = $location->quality;

								if (preg_match('/\/(CH_.*)\/manifest\.mpd/ui', $ott_url, $matches))
									$npvr_id = $matches[1];
								else if (preg_match('/\/(CH_.*)\/variant\.m3u8/ui', $ott_url, $matches))
									$npvr_id = $matches[1];

								$bcid = md5("$num-$ott_url");

								break;
							}
						}
					}

					$iteration++;
				}

				if (empty($ott_url))
				{
					$iteration++;
					$ott_url = trim($channel->ottURL);

					if (empty($ott_url))
						break;

					$bcid = md5("$num-$ott_url");

					if (isset($this->_tv_channels['numbers'][$bcid]))
						if ($this->_tv_channels['numbers'][$bcid] <= $num)
							break;

					$epg = empty($channel->epg->id)? array() : (is_array($channel->epg->id)? $channel->epg->id : array($channel->epg->id));
					$quality = $channel->quality;

					if (preg_match('/\/(CH_.*)\/manifest\.mpd/ui', $ott_url, $matches))
						$npvr_id = $matches[1];
					else if (preg_match('/\/(CH_.*)\/variant\.m3u8/ui', $ott_url, $matches))
						$npvr_id = $matches[1];
				}


				$uhd_npvr_sign = preg_match('/u(ltra|)hd|4k(_.+|)$/ui', $npvr_id);
				$hd_npvr_sign = !$uhd_npvr_sign && (strpos($npvr_id, 'HD') !== false);

				if (($quality == 'SD') || $sd_name_sign)
					$this->_tv_channels['bcnames']['sd'][$bcid] = $title;//$bcname;
				else if (($quality == '4K') || $uhd_npvr_sign || $uhd_name_sign)
					$this->_tv_channels['bcnames']['4k'][$bcid] = preg_match('/^(hd|ultra|4k)\s+/ui', $title)? $title : (preg_match('/\s+ultra$/ui', $title)? $title : $title . ' 4K');//preg_match('/^(hd|ultra|4k)\s+/ui', $bcname)? $bcname : (preg_match('/\s+ultra$/ui', $bcname)? $bcname : preg_replace('/\s+(hd|uhd|4k)$/ui', '', $bcname) . ' 4K');
				else if (($quality == 'HD') || $hd_npvr_sign || $hd_name_sign)
					$this->_tv_channels['bcnames']['hd'][$bcid] = preg_match('/\s+hd\s+/ui', $title)? $title : $title . ' HD';//preg_match('/^hd\s+/ui', $bcname)? $bcname : preg_replace('/\s+(hd)$/ui', '', $bcname) . ' HD';
				else
					$this->_tv_channels['bcnames']['sd'][$bcid] = $bcname;

				$this->_tv_channels['packages'][$bcid][$package] = $this->_packages[$package];
				$this->_tv_channels['numbers'][$bcid] = $num;
				$this->_tv_channels['channels'][$bcid] =
					array
					(
						'id' => $title_id,
						'npvr_id' => $npvr_id,
						'number' => $num,
						'title' => $title,
						'desc' => trim(preg_replace('/\r\n|\r|\n/u', ' ', $channel->desc)),
						'logo' => trim($channel->logo),
						'logo_hash' => trim($channel->logo_hash),
						'groups' => $groups,
						'epg' => $epg,
						'ott_url' => $ott_url,
					);

				$ott_url = '';
			}
		}

		return
			count(array_unique($this->_tv_channels['numbers'])) - $c;
	}

	public function get_tv_channels($grouping_similars_channels)
	{
		if (empty($this->_tv_channels))
			return null;

		$this->_packages = null;
		$channels_arr = &$this->_tv_channels['channels'];
		$bcnames_arr = &$this->_tv_channels['bcnames'];
		$packages_arr = &$this->_tv_channels['packages'];
		$unused_numbers = array_diff(range(1,999), $this->_tv_channels['numbers']);
		$prev_channel_number = 0;
		$prev_channel_id = '';
		$channels = array();
		$qualities_arr = array('sd', 'hd', '4k');
		uasort($channels_arr, 'self::sort_channels');

		foreach($channels_arr as $bcid => $data)
		{
			$unused_number = '';

			if ($prev_channel_number == $data['number'])
			{
				if (stripos($data['id'], $prev_channel_id) !== false)
				{
					foreach($qualities_arr as $q)
					{
						if (!empty($bcnames_arr[$q][$bcid]))
						{
							if (isset($channels[$prev_channel_number]['sub']))
							{
								foreach($channels[$prev_channel_number]['sub'] as $sub_data)
									if ($data['ott_url'] == $sub_data['ottUrl'])
										break 2;

								$channels[$prev_channel_number]['sub'][$bcid] =
									array
									(
										'bcId' => $bcid,
										'bcNumber' => $data['number'],
										'bcName' => $bcnames_arr[$q][$bcid],
										'npvrId' => $data['npvr_id'],
										'logo' => $this->get_icon_url($data['logo']),
										'logo_hash' => $data['logo_hash'],
										'quality' => $q,
										'genres' => $data['groups'],
										'epg' => $data['epg'],
										'packages' => $packages_arr[$bcid],
									);
							}
						}
					}
				}
				else
				{
					foreach($qualities_arr as $q)
					{
						if (!empty($bcnames_arr[$q][$bcid]))
						{
							foreach($channels[$prev_channel_number]['sub'] as $sub_data)
								if ($data['ott_url'] == $sub_data['ottUrl'])
										break 2;

							$channels[$prev_channel_number]['sub'][$bcid] =
								array
								(
									'bcId' => $bcid,
									'bcNumber' => $data['number'],
									'bcName' => $bcnames_arr[$q][$bcid],
									'npvrId' => $data['npvr_id'],
									'logo' => $this->get_icon_url($data['logo']),
									'logo_hash' => $data['logo_hash'],
									'quality' => $q,
									'genres' => $data['groups'],
									'epg' => $data['epg'],
									'packages' => $packages_arr[$bcid],
								);
						}
					}
				}
			}
			else
			{
				if ($grouping_similars_channels && ($prev_channel_id == $data['id']) && (!isset($this->_not_grouped_channels[$prev_channel_number]) || ($this->_not_grouped_channels[$prev_channel_number] <> $data['id'])))
				{
					foreach($qualities_arr as $q)
					{
						if (!empty($bcnames_arr[$q][$bcid]))
							$channels[$prev_channel_number]['sub'][$bcid] =
								array
								(
									'bcId' => $bcid,
									'bcNumber' => $data['number'],
									'bcName' => $bcnames_arr[$q][$bcid],
									'npvrId' => $data['npvr_id'],
									'logo' => $this->get_icon_url($data['logo']),
									'logo_hash' => $data['logo_hash'],
									'quality' => $q,
									'genres' => $data['groups'],
									'epg' => $data['epg'],
									'packages' => $packages_arr[$bcid],
								);
					}
				}
				else
				{
					if ($grouping_similars_channels && isset($channels[$data['number']]))
					{
						if (stripos($channels[$data['number']]['id'], $data['id']) === false)
						{
							foreach($unused_numbers as $idx => $unused_number)
								if ($unused_number > $data['number'])
								{
									unset($unused_numbers[$idx]);
									$prev_channel_number = $unused_number;
									$prev_channel_id = $data['id'];
									$channels[$unused_number]['id'] = $data['id'];
									$channels[$unused_number]['title'] = $data['title'];
									$channels[$unused_number]['desc'] = $data['desc'];
									$channels[$unused_number]['groups'] = $data['groups'];

									foreach($qualities_arr as $q)
									{
										if (!empty($bcnames_arr[$q][$bcid]))
											$channels[$unused_number]['sub'][$bcid] =
												array
												(
													'bcId' => $bcid,
													'bcNumber' => $data['number'],
													'bcName' => $bcnames_arr[$q][$bcid],
													'npvrId' => $data['npvr_id'],
													'logo' => $this->get_icon_url($data['logo']),
													'logo_hash' => $data['logo_hash'],
													'quality' => $q,
													'genres' => $data['groups'],
													'epg' => $data['epg'],
													'packages' => $packages_arr[$bcid],
												);

										break 2;
									}
								}
						}
					}
					else
					{
						if (isset($channels[$data['number']]) && (stripos($data['id'], $channels[$data['number']]['id']) === false))
						{
							foreach($unused_numbers as $idx => $unused_number)
								if ($unused_number > $data['number'])
								{
									unset($unused_numbers[$idx]);
									$channels[$unused_number]['id'] = $data['id'];
									$channels[$unused_number]['title'] = $data['title'];
									$channels[$unused_number]['desc'] = $data['desc'];
									$channels[$unused_number]['groups'] = $data['groups'];

									foreach($qualities_arr as $q)
									{
										if (!empty($bcnames_arr[$q][$bcid]))
											$channels[$unused_number]['sub'][$bcid] =
												array
												(
													'bcId' => $bcid,
													'bcNumber' => $data['number'],
													'bcName' => $bcnames_arr[$q][$bcid],
													'npvrId' => $data['npvr_id'],
													'logo' => $this->get_icon_url($data['logo']),
													'logo_hash' => $data['logo_hash'],
													'quality' => $q,
													'genres' => $data['groups'],
													'epg' => $data['epg'],
													'packages' => $packages_arr[$bcid],
												);

										break 2;
									}
							}
						}
						else
						{
							$prev_channel_number = $data['number'];
							$prev_channel_id = $data['id'];

							if (!isset($channels[$prev_channel_number]))
							{
								$channels[$prev_channel_number]['id'] = $prev_channel_id;
								$channels[$prev_channel_number]['title'] = $data['title'];
								$channels[$prev_channel_number]['desc'] = $data['desc'];
								$channels[$prev_channel_number]['groups'] = $data['groups'];
							}

							foreach($qualities_arr as $q)
								if (!empty($bcnames_arr[$q][$bcid]))
									$channels[$prev_channel_number]['sub'][$bcid] =
										array
										(
											'bcId' => $bcid,
											'bcNumber' => $data['number'],
											'bcName' => $bcnames_arr[$q][$bcid],
											'npvrId' => $data['npvr_id'],
											'logo' => $this->get_icon_url($data['logo']),
											'logo_hash' => $data['logo_hash'],
											'quality' => $q,
											'genres' => $data['groups'],
											'epg' => $data['epg'],
											'packages' => $packages_arr[$bcid],
										);
						}
					}
				}
			}

			$number = empty($unused_number)? $prev_channel_number : $unused_number;

			if (isset($channels[$number]['sub'][$bcid]))
				$channels[$number]['sub'][$bcid]['ottUrl'] = $data['ott_url'];

			if (!isset($channels[$number]['sub']))
			{
				unset($channels[$number]);
				continue;
			}
		}

		$this->_tv_channels = null;

		return
			array(
				'groups' => $this->_tv_groups,
				'channels' => $channels,
		);
	}

	public function get_tv_packages()
	{
		$this->_tv_channels = array();
		$this->_tv_groups = array();

		if (empty($this->cur_location_id))
			return false;

		if (!$data = $this->xml_request((defined('DEBUG_MODE_ON') && file_exists('/D/ncdxml/list_services_terminal.xml'))? '/D/ncdxml/list_services_terminal.xml' : decode_str('YWaHR0cHM6Ly9icmlnYWRpci5teWR1bmUucnUvaG9tZV90di93aW5rL2xpc3Rfc2VydmljZXNfdGVybWluYWwueG1s')))
			return false;

		if (empty($this->_packages))
			foreach($data->service as $service)
				if ($service->type == 'CHANNELPACKAGE')
				{
					$service_name = trim($service->name, " .,\n");

					if (!empty($service_name))
						$this->_packages[$service->id] = $service_name;
				}

		return $this->_packages;
	}

	public function get_locations_list($location_id = null)
	{
		if (empty($this->_locations))
			$this->load_locations_list();

		if (isset($this->_locations[$location_id]))
		{
			foreach($this->_locations[$location_id]['sub'] as $sub_id => $sub_data)
				$result[$sub_id] = $sub_data['name'];
		}
		else
			foreach($this->_locations as $id => $data)
				$result[$id] = $data['name'];

		return empty($result)? array() : $result;
	}

	public function get_location_info($id = null)
	{
		if (empty($this->_locations))
			$this->load_locations_list();

		$sub_location_id = empty($id)? $this->cur_sub_location_id : $id;

		foreach ($this->_locations as $location_id => $location)
			if (isset($location['sub'][$sub_location_id]))
			{
				$result =
					array
					(
						'mrf' => $this->_locations[$location_id]['mrf'],
						'location_id' => $location_id,
						'location_name' => $this->_locations[$location_id]['name'],
						'sub_location_id' => $sub_location_id,
						'sub_location_name' => $this->_locations[$location_id]['sub'][$sub_location_id]['name'],
						'timezone' => $this->_locations[$location_id]['sub'][$sub_location_id]['timezone'],
						'offset_sec' => $this->_locations[$location_id]['sub'][$sub_location_id]['offset_sec'],
						'yid' => empty($this->_locations[$location_id]['sub'][$sub_location_id]['yid'])? 0 :  $this->_locations[$location_id]['sub'][$sub_location_id]['yid'],
					);
			}

		return
			empty($result)? null : (object) $result;
	}

	public function set_location($id)
	{
		if ($location_info = $this->get_location_info($id))
		{
			$this->cur_mrf = $location_info->mrf;
			$this->cur_location_id = $location_info->location_id;
			$this->cur_sub_location_id = $location_info->sub_location_id;

			hd_print("Set location to {$this->cur_mrf}-{$this->cur_location_id}-{$this->cur_sub_location_id}");
			return true;
		}

		hd_print("Warning! Unable to set location \"$id\"");
		return false;
	}

	public function get_channel_epg($id, $start_time, $end_time)
	{
		if ($response = $this->api_request('GET', sprintf('/api/v2/user/epg?channels_ids=%s&start_time=%s&end_time=%s', $id, $start_time, $end_time), null, false))
			foreach ($response->items as $item)
				if (is_array($item->channel_programs))
				{
					$result = array();

					foreach ($item->channel_programs as $program)
					{
						$genre = is_array($program->genres)? array_pop($program->genres) : '';

						$result[] =
							array
							(
								'id' => $program->original_id,
								'start_time' => $program->start_time,
								'end_time' => $program->end_time,
								'age_level' => $program->age_level->name,
								'genre' => $genre->name,
								'name' => $program->name,
								'description' => $program->description,
								'logo' => $this->api_img_base_url . $program->logo,
							);
					}

					return $result;
				}

		return false;
	}
}

?>
