<?php
require_once 'lib/hashed_array.php';
require_once 'lib/tv/abstract_tv.php';
require_once 'lib/tv/default_epg_item.php';
require_once 'i24h_channel.php';

class I24hTv extends AbstractTv
{
    private $session;
    private $solo;
    private $products;
    private $id2num = array();
    private $num2id = array();

    public function __construct($session)
    {
        $this->session = $session;

        $f = fopen('/tmp/sysinfo.txt', 'r');
        $text=fread($f, 1024);
        fclose($f);
        $pos = strpos($text, 'solo4k');
        $posR11 = strpos($text,'_r11');

        if ($posR11 === false ) {
            if ($pos === false) {
                $this->solo = 'lower_cpu_load:1,';
            } else {
                $this->solo = '';
            }
        }else{
            $this->solo = '';
        }
		
		$this->products = array();
        
        parent::__construct(
            AbstractTv::MODE_CHANNELS_N_TO_M,
            I24hConfig::TV_FAVORITES_SUPPORTED,
            true);
    }

    public function get_fav_icon_url()
    {
        return I24hConfig::FAV_CHANNEL_GROUP_PANEL_ICON_PATH;
    }

    protected function load_channels(&$plugin_cookies)
    {
        $this->session->check_logged_in();
        $this->channels = new HashedArray();
        $this->groups = new HashedArray();

        try {
            $doc = HD::http_get_document(
                sprintf($this->session->get_api_server() . I24hConfig::CHANNEL_IN_PACKET, $this->session->get_token()),
                $this->session->get_http_opts());
        } catch (Exception $e) {
            throw new DuneException(
                'HTTP network error', 0,
                ActionFactory::show_error(
                    true,
                    'Ошибка связи',
                    array(
                        'Не удаётся подключиться к IPTV-серверу.',
                        'Проверьте подключение к сети Интернет.')));
        }

        $xml = simplexml_load_string($doc);

        if ($xml === false) {
            hd_print("Error: can not parse XML document.");
            hd_print("XML-text: $doc.");
            throw new Exception('Illegal XML document');
        }

        if ($xml->getName() !== 'root') {
            hd_print("Error: unexpected node '" . $xml->getName() . "'. Expected: 'response'");
            throw new Exception('Invalid XML document');
        }

        $tariffs = array();
        foreach ($xml->children() as $packets) {
            foreach ($packets->channels->children() as $channels) {

                $ch_id = strval($channels->id);

                if (empty($tariffs[$ch_id])) $tariffs[$ch_id] = array();

                if (!in_array('"' . strval($packets->name) . '"', $tariffs[$ch_id])) {
                    $tariffs[$ch_id][] = '"' . strval($packets->name) . '"';
                }
            }
        }
        foreach ($xml->children() as $packets) {
            foreach ($packets->available->children() as $dop_tariffs) {
                foreach ($dop_tariffs->channels->children() as $channels){

                    $ch_id = strval($channels->id);
                    if (empty($tariffs[$ch_id])) $tariffs[$ch_id] = array();

                    if (!in_array('доп. пакет "'.strval($dop_tariffs->name).'"',$tariffs[$ch_id])) {
                        $tariffs[$ch_id][] = 'доп. пакет "' . strval($dop_tariffs->name) . '"';
                    }
                }
            }
        }

        if ($this->is_favorites_supported()) {
            $this->groups->put(
                new FavoritesGroup(
                    $this,
                    '__favorites',
                    I24hConfig::FAV_CHANNEL_GROUP_CAPTION,
                    'plugin_file://img/cat/fav.png',
                    'plugin_file://img/cat/fav.png'
            ));
        }

        $active_list = array();
        $need_req_pass = empty($plugin_cookies->need_password_sextv)?'no':$plugin_cookies->need_password_sextv;

        // Запросим из api список каналов доступных пользователю
        try {
            $doc = HD::http_get_document(
                sprintf($this->session->get_api_server() . I24hConfig::CHANNEL_USER_LIST, $this->session->get_token()),
                $this->session->get_http_opts());
        } catch (Exception $e) {
            throw new DuneException(
                'HTTP network error', 0,
                ActionFactory::show_error(
                    true,
                    'Ошибка связи',
                    array(
                        'Не удаётся подключиться к IPTV-серверу.',
                        'Проверьте подключение к сети Интернет.')));
        }

        $xml_user = simplexml_load_string($doc);

        if ($xml_user === false) {
            hd_print("Error: can not parse XML document.");
            hd_print("XML-text: $doc.");
            throw new Exception('Illegal XML document');
        }

        if ($xml_user->getName() !== 'root') {
            hd_print("Error: unexpected node '" . $xml_user->getName() . "'. Expected: 'response'");
            throw new Exception('Invalid XML document');
        }
        // пробежимся по каналам доступные пользователю
        foreach ($xml_user->children() as $users_channels) {
            // Добавим номер канала для преобразования из id
#            $this->id2num[intval($users_channels->id)]=empty($users_channels->num)?intval($users_channels->id):intval($users_channels->num);
#            $ch_id = $this->id2num[intval($users_channels->id)];
            $ch_id = intval($users_channels->id);
#            $this->num2id[$this->id2num[intval($users_channels->id)]] = $users_channels->id;
            // Канал доступен пользователю, созраним его в хеше
            $active_list[$ch_id] = 1;
        }

#        hd_print(print_r($this->id2num,true));

        // Запросим из API список категорий с каналами доступных провайдеру
        try {
            $doc = HD::http_get_document(
                sprintf($this->session->get_api_server() . I24hConfig::CHANNEL_LIST_URL, $this->session->get_token()),
                $this->session->get_http_opts());
        } catch (Exception $e) {
            throw new DuneException(
                'HTTP network error', 0,
                ActionFactory::show_error(
                    true,
                    'Ошибка связи',
                    array(
                        'Не удаётся подключиться к IPTV-серверу.',
                        'Проверьте подключение к сети Интернет.')));
        }

        $xml = simplexml_load_string($doc);

        if ($xml === false) {
            hd_print("Error: can not parse XML document.");
            hd_print("XML-text: $doc.");
            throw new Exception('Illegal XML document');
        }

        if ($xml->getName() !== 'root') {
            hd_print("Error: unexpected node '" . $xml->getName() . "'. Expected: 'response'");
            throw new Exception('Invalid XML document');
        }


        $all_channels = array();

        // Список категорий и каналов доступных провайдеру
        foreach ($xml->children() as $xml_tv_category) {

            if (intval($xml_tv_category->id) == 16) {
                // Создаем категорию Все каналы

                $all_Group = new AllChannelsGroup(
                    $this,
                    I24hConfig::ALL_CHANNEL_GROUP_CAPTION,
                    'plugin_file://img/cat/all.png',
                    'plugin_file://img/cat/alls.png');


                $this->groups->put($all_Group);
               // Заполнять каналами группу "Все каналы" не надо
                continue;
            }else {
                // Создаем все категории доступных провайдеру
                $this->groups->put(
                    new DefaultGroup(
                        intval($xml_tv_category->id),
                        strval($xml_tv_category->name),
                        'plugin_file://img/cat/' . strval($xml_tv_category->id) . '.png',
                        'plugin_file://img/cat/' . strval($xml_tv_category->id) . 's.png'
                    ));
            }

#            hd_print("!!!!!!!!!!!!!");

            // Пробежимся по всем каналам доступные провайдеру и заполним массив с данными по каналу
            foreach ($xml_tv_category->channels->children() as $ch) {
#                if (!empty($this->id2num[intval($ch->id)])) {
#                }else{
#                    $this->id2num[intval($ch->id)] = intval($ch->id);
#                }
#                $ch_id = $this->id2num[intval($ch->id)];
                $ch_id = intval($ch->id);
#                $this->num2id[$this->id2num[$ch_id]] = $ch_id;

                $bool_parental = false;

                if (!empty($active_list[$ch_id])){
                    // Доступный канал
                    if (($need_req_pass=='yes') && (!empty($ch->age)&&$ch->age==18) && ($this->session->get_parental_code()!='0000') ){
                        $bool_parental = true;
                    }else{
                        $bool_parental = false;
                    }
                    $img = strval($ch->icon);
                    $url = "";

                }else{
                    // Закрытый канал
                    $img = 'http://static.24h.tv/dune/channel/lock.png';
                    $url = "passive";
                }

                if (empty($all_channels[$ch_id])) {
                    $channel =
                        new I24hChannel(
                            $ch_id,
                            strval($ch->name),
                            $img . '?h=100',
                            $url,
                            intval($ch->num),
                            intval($ch->archived_days),
                            2,
                            intval($ch->archived_days) > 0 ? true : false,
                            $bool_parental,
                            $img . '?h=100',
                            empty($tariffs[$ch_id]) ? null : $tariffs[$ch_id]
                        );

                    $this->channels->put($channel);
                    $all_channels[$ch_id] = $channel;
                }else{
                    $channel = $all_channels[$ch_id];
                }
                if (intval($xml_tv_category->id) != 16) {
                    $gp = $this->groups->get(intval($xml_tv_category->id));
                    $gp->add_channel($channel);
                    $channel->add_group($gp);
                }

            }
        }

    }

    public function get_tv_info(MediaURL $media_url, &$plugin_cookies)
    {
        $this->session->ensure_logged_in($plugin_cookies);
        return parent::get_tv_info($media_url, &$plugin_cookies);
    }

    public function get_tv_stream_url($playback_url, &$plugin_cookies)
    {
        $url = $this->session->api_get_stream_url($playback_url);
        if (substr($url, 0, 1) === '/') {
        	$ss_bin_path = DuneSystem::$properties['install_dir_path'] . '/bin';
        	$cmd = $ss_bin_path . "/play.sh $ss_bin_path > /tmp/rrr.log";
        	$s = shell_exec($cmd);
        	if (!empty($s)) return 'http://ts://localhost:8081'.$url.'|||dune_params|||ll_prebuf_for_http_ts:1,'.$this->solo.'psi_opt:2,buffering_ms:300,ss_for_http_ts:1';
        } else {
        	return $url;
        }
    }
    
    public function save_history($product_id, &$plugin_cookies)
    {
    	if (isset($plugin_cookies->prodhist)) {
    		$prodhist = json_decode($plugin_cookies->prodhist, true);
    	} else {
    		$prodhist = array();
    	}
    	
    	foreach ($prodhist as $k => $val) {
    		if (($val['type'] == 1) && ($val['product_id'] == $product_id)) {
    			unset($prodhist[$k]);
    		}
    	}
    	
    	$len = array_unshift($prodhist, array(
    		'type' => 1,
    		'product_id' => $product_id));
    	
    	if ($len > 8) {
    		array_pop($prodhist);
    	}
    	$plugin_cookies->prodhist = json_encode($prodhist);
    }


    public function get_tv_playback_url($channel_id, $archive_ts, $protect_code, &$plugin_cookies)
    {
        $channel = $this->get_channel($channel_id);
        $protect_code = empty($protect_code)?'':$protect_code;
        $restrict_ch = true;
        $need_req_pass = empty($plugin_cookies->need_password_sextv)?'no':$plugin_cookies->need_password_sextv;

        if (!in_array($plugin_cookies->stream_type,array('local','local_low','hls'))){
            $plugin_cookies->stream_type = 'local';
        }

        if ($channel->is_protected() && $need_req_pass=='yes' && $this->session->get_parental_code()!='0000'){
            if ($protect_code === $this->session->get_parental_code()){
                $restrict_ch = true;
            }else{
                $restrict_ch = false;
            }
        }else{
            $restrict_ch = true;
        }

        if ($restrict_ch){
            $archive_ts = empty($archive_ts) ? 0 : $archive_ts;
            $archive_ts = ($archive_ts == -1) ? 0 : $archive_ts;
            $this->ensure_channels_loaded($plugin_cookies);
            $st_type = empty($plugin_cookies->stream_type) ? 'local' : $plugin_cookies->stream_type;

            $ss_bin_path = DuneSystem::$properties['install_dir_path'] . '/bin';
            $cmd = $ss_bin_path . "/play.sh $ss_bin_path > /tmp/rrr.log";
            $s = shell_exec($cmd);

            // Запросим из API урл на вещание
            try {
                $doc = HD::http_get_document(
                    sprintf($this->session->get_api_server() . I24hConfig::CHANNEL_URL, $channel_id, $archive_ts, $st_type, $this->session->get_token()),
                    $this->session->get_http_opts());
            } catch (Exception $e) {
                throw new DuneException(
                    'HTTP network error', 0,
                    ActionFactory::show_error(
                        true,
                        'Ошибка связи',
                        array(
                            'Не удаётся подключиться к IPTV-серверу.',
                            'Проверьте подключение к сети Интернет.')));
            }

            $xml = simplexml_load_string($doc);

            if ($xml === false) {
                hd_print("Error: can not parse XML document.");
                hd_print("XML-text: $doc.");
                throw new Exception('Illegal XML document');
            }

            if ($xml->getName() !== 'root') {
                hd_print("Error: unexpected node '" . $xml->getName() . "'. Expected: 'response'");
                throw new Exception('Invalid XML document');
            }
            $url = '';
            switch ($st_type) {
                case "hls":
                    $url = strval($xml->hls);
                    break;
                case "local":
                    $url = strval($xml->local);
                    break;
                case "local_low":
                    $url = strval($xml->local_low);
                    break;
                default:
                    throw new DuneException(
                        'HTTP network error', 0,
                        ActionFactory::show_error(
                            true,
                            'Ошибка связи',
                            array(
                                'Не удаётся подключиться к IPTV-серверу.',
                                'Проверьте подключение к сети Интернет.')));
            }

            $channel = $this->get_channel($channel_id);
            if ($channel->get_streaming_url() != "passive") {

                if ($archive_ts > 0) {
                    if (isset($this->products[$channel_id][intval($archive_ts)])) {
                        $pid = $this->products[$channel_id][intval($archive_ts)];
                        if (!$channel->is_protected()) $this->save_history($pid, $plugin_cookies);
                    }
                    return preg_replace('/^http:\/\/localhost:/', 'http://ts://localhost:', $url) .
                        '|||dune_params|||ll_prebuf_for_http_ts:1,' . $this->solo . 'psi_opt:2,buffering_ms:300,ss_for_http_ts:1,keep_pic:0';
                } else {
                    return preg_replace('/^http:\/\/localhost:/', 'http://ts://localhost:', $url) .
                        '|||dune_params|||ll_prebuf_for_http_ts:1,' . $this->solo . 'psi_opt:2,buffering_ms:300,ss_for_http_ts:1,keep_pic:0';
                }
            }else{
                // Возврат матраса
                return 'http://static.24h.tv/dune/main/matras.jpg';
            }
//            return;
        }else{
            $channel = $this->get_channel($channel_id);
            if ($channel->get_streaming_url() == "passive") {
                // Возврат матраса
                return 'http://static.24h.tv/dune/main/matras.jpg';
            }else {
                return "protected";
            }
//            return "protected";
        }

    }

    public function get_day_epg_iterator($channel_id, $day_start_ts, &$plugin_cookies)
    {
        if (I24hConfig::EPG_URL_FORMAT == null)
            return array();

        try
        {
            $doc =
                HD::http_get_document(
                    sprintf(
                        $this->session->get_api_server() . I24hConfig::EPG_URL_FORMAT,

                        $channel_id,
                        $day_start_ts,
                        $day_start_ts+24*3600,
                        $this->session->get_token()
                        ));
        }
        catch (Exception $e)
        {
            throw new DuneException(
                'HTTP network error', 0,
                ActionFactory::show_error(
                    true,
                    'Ошибка связи',
                    array(
                        'Не удаётся подключиться к IPTV-серверу.',
                        'Проверьте подключение к сети Интернет.')));
        }
     
        $xml = simplexml_load_string($doc);

        if ($xml === false)
        {
            hd_print("Error: can not parse XML document.");
            hd_print( "XML-text: $doc.");
            throw new Exception('Illegal XML document');
        }

        if ($xml->getName() !== 'root')
        {
            hd_print("Error: unexpected node '" . $xml->getName() . "'. Expected: 'NewDataSet'");
            throw new Exception('Invalid XML document');
        }

        $epg = array();

        foreach ($xml->children() as $epg_item)
        {
            $epg[] =
                new DefaultEpgItem(
                    strval($epg_item->program->title),
                    strval($epg_item->program->description),
                    intval($epg_item->timestamp),
                    intval($epg_item->timestamp)+intval($epg_item->duration));
                
            if (!isset($this->products[$channel_id])) {
            	$this->products[$channel_id] = array();
            }
            $this->products[$channel_id][intval($epg_item->timestamp)] = intval($epg_item->id);
        }

        return
            new EpgIterator(
                $epg,
                $day_start_ts,
                $day_start_ts + 86400);
    }

    public function folder_entered(MediaURL $media_url, &$plugin_cookies)
    {
        $this->session->ensure_logged_in($plugin_cookies);
    }
    
    public function have_channel($channel_id)
    {
        $c = $this->channels->get($channel_id);
        if (is_null($c))
            return false;
        return true;
    }

}

?>
