<?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();

        $url = sprintf($this->session->get_api_server() . I24hConfig::CHANNEL_IN_PACKET, $this->session->get_token());

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

        $tariffs = array();
        foreach ($doc as $packets) {
            foreach ($packets->channels 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 ($doc as $packets) {
            foreach ($packets->available as $dop_tariffs) {
                foreach ($dop_tariffs->channels 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 список каналов доступных пользователю
        $url = sprintf($this->session->get_api_server() . I24hConfig::CHANNEL_USER_LIST, $this->session->get_token());
        try {
            $doc = $this->session->api_call($url);
        } catch (Exception $e) {
            throw new DuneException(
                'HTTP network error', 0,
                ActionFactory::show_error(
                    true,
                    'Ошибка связи',
                    array('Не удаётся подключиться к серверу.', 'Проверьте подключение к сети Интернет.')));
        }
        // пробежимся по каналам доступные пользователю
        foreach ($doc as $users_channels) {
            // Добавим номер канала для преобразования из id
            $ch_id = intval($users_channels->id);
            // Канал доступен пользователю, созраним его в хеше
            $active_list[$ch_id] = 1;
        }
        // Запросим из API список категорий с каналами доступных провайдеру
        try {
            if (I24HSettings::$CHANNELS_SORT == 'num') {
                $url = sprintf($this->session->get_api_server() . I24hConfig::CHANNEL_LIST_URL_NUM, $this->session->get_token());
            } else {
                $url = sprintf($this->session->get_api_server() . I24hConfig::CHANNEL_LIST_URL, $this->session->get_token());
            }
            $doc = $this->session->api_call($url);
        } catch (Exception $e) {
            throw new DuneException(
                'HTTP network error', 0,
                ActionFactory::show_error(
                    true,
                    'Ошибка связи',
                    array('Не удаётся подключиться к серверу.', 'Проверьте подключение к сети Интернет.')));
        }

        $all_channels = array();
        $open_channels = array();
        $closed_channels = array();
        foreach ($doc as $tv_category) {
            if (intval($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);
                // Заполнять каналами группу "Все каналы"
                foreach ($tv_category->channels as $ch) {
                    $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;
                        }
                        $open_channels[$ch->id]["id"] = $ch->id;
                        $open_channels[$ch->id]["name"] = $ch->name;
                        $open_channels[$ch->id]["img"] = I24HSettings::$MEDIA_URL.$ch->id.".jpeg?cover=true&w=320&h=168&crop=true";
                        $open_channels[$ch->id]["archived_days"] = $ch->archived_days;
                        $open_channels[$ch->id]["num"] = $ch->num;
                        $open_channels[$ch->id]["bool_parental"] = $bool_parental;
                        $open_channels[$ch->id]["url"] = "";
                        $open_channels[$ch->id]["trf"] = empty($tariffs[$ch->id]) ? null : $tariffs[$ch_id];
                        $open_channels[$ch->id]["group"] = array();
                    } else {
                        // Закрытый канал
                        $closed_channels[$ch->id]["id"] = $ch->id;
                        $closed_channels[$ch->id]["name"] = $ch->name;
                        $closed_channels[$ch->id]["img"] = I24HSettings::$LOCK_IMAGE;
                        $closed_channels[$ch->id]["archived_days"] = $ch->archived_days;
                        $closed_channels[$ch->id]["num"] = $ch->num;
                        $closed_channels[$ch->id]["bool_parental"] = $bool_parental;
                        $closed_channels[$ch->id]["url"] = "passive";
                        $closed_channels[$ch->id]["trf"] = empty($tariffs[$ch->id]) ? null : $tariffs[$ch_id];
                        $closed_channels[$ch->id]["group"] = array();
                    }
                }
            }
        }

        foreach ($doc as $tv_category) {
            if ($tv_category->id != 16) {
                if (I24hConfig::DEBUG) hd_print('group id = ' . $tv_category->id . ' name = ' . $tv_category->name . ' channels_count = ' . count($tv_category->channels));
                if (count($tv_category->channels) > 0) {
                    // Создаем все категории доступных провайдеру
                    $this->groups->put(
                        new DefaultGroup(
                            intval($tv_category->id),
                            strval($tv_category->name),
                            'plugin_file://img/cat/' . strval($tv_category->id) . '.png',
                            'plugin_file://img/cat/' . strval($tv_category->id) . 's.png'
                        ));

                    if (I24hConfig::DEBUG) hd_print($tv_category->name . " icon = " . 'plugin_file://img/cat/' . $tv_category->id . '.png panel icon = ' . 'plugin_file://img/cat/' . $tv_category->id . 's.png');

                    foreach ($tv_category->channels as $ch) {
                        if (!empty($open_channels[$ch->id])) {
                            $open_channels[$ch->id]["group"][] = $tv_category->id;
                        }elseif (!empty($closed_channels[$ch->id])){
                            $closed_channels[$ch->id]["group"][] = $tv_category->id;
                        } else {
                            $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;
                                }
                                $open_channels[$ch->id]["id"] = $ch->id;
                                $open_channels[$ch->id]["name"] = $ch->name;
                                $open_channels[$ch->id]["img"] = "http://media.24h.tv/".$ch->id.".jpeg?cover=true&w=320&h=168&crop=true";
                                $open_channels[$ch->id]["archived_days"] = $ch->archived_days;
                                $open_channels[$ch->id]["num"] = $ch->num;
                                $open_channels[$ch->id]["bool_parental"] = $bool_parental;
                                $open_channels[$ch->id]["url"] = "";
                                $open_channels[$ch->id]["trf"] = empty($tariffs[$ch->id]) ? null : $tariffs[$ch_id];
                                $open_channels[$ch->id]["group"] = array();
                                $open_channels[$ch->id]["group"][] = $tv_category->id;
                            } else {
                                // Закрытый канал
                                $closed_channels[$ch->id]["id"] = $ch->id;
                                $closed_channels[$ch->id]["name"] = $ch->name;
                                $closed_channels[$ch->id]["img"] = "http://static.24h.tv/dune/channel/lock.png?w=320&h=168";
                                $closed_channels[$ch->id]["archived_days"] = $ch->archived_days;
                                $closed_channels[$ch->id]["num"] = $ch->num;
                                $closed_channels[$ch->id]["bool_parental"] = $bool_parental;
                                $closed_channels[$ch->id]["url"] = "passive";
                                $closed_channels[$ch->id]["trf"] = empty($tariffs[$ch->id]) ? null : $tariffs[$ch_id];
                                $closed_channels[$ch->id]["group"] = array();
                                $closed_channels[$ch->id]["group"][] = $tv_category->id;
                            }
                        }
                    }
                }
            }
        }
        $all_channels = array_merge($open_channels, $closed_channels);
        foreach ($all_channels as $ch) {
            if (empty($ch["id"])) {
                if (I24hConfig::DEBUG) hd_print(print_r($ch, true));
            }
            $channel = new I24hChannel(
                $ch["id"],
                $ch["name"],
                $ch["img"],
                $ch["url"],
                $ch["num"],
                $ch["archived_days"],
                $this->session->get_has_tariffs() ? 2 : 0,
                $this->session->get_has_tariffs() ? ($ch["archived_days"] > 0 ? true : false) : 0,
                $ch["bool_parental"],
                $ch["img"],
                $ch["trf"]
            );
            $this->channels->put($channel);
            foreach ($ch["group"] as $gp_id) {
                $gp = $this->groups->get($gp_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)
    {

        if (I24hConfig::DEBUG) hd_print("get_tv_playback_url: channel_id = " . $channel_id);

        $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/receive.log";
            $s = shell_exec($cmd);

            if ($channel->get_streaming_url() != "passive") {
                // Запросим из API урл на вещание
                $url = sprintf($this->session->get_api_server() . I24hConfig::CHANNEL_URL, $channel_id, $archive_ts, $st_type, $this->session->get_token());
                try {
                    $doc = $this->session->api_call($url);
                } catch (Exception $e) {
                    if (I24hConfig::DEBUG) hd_print("Exception = " . $e->getMessage() . " return matras " . I24HSettings::$MATRAS_GEO_URL);
                    if ($e->getMessage() == "403") {
                        // Geo Matras
                        return I24HSettings::$MATRAS_GEO_URL;
                    }else{
                        return I24HSettings::$MATRAS_URL;
                    }
                }

                if (!empty($doc->hls)){
                    $url = $doc->hls;
                }elseif (!empty($doc->local)){
                    $url = $doc->local;
                }elseif (!empty($doc->local_low)){
                    $url = $doc->local_low;
                }else{
                    throw new DuneException(
                        'HTTP network error', 0,
                        ActionFactory::show_error(
                            true,
                            'Ошибка связи',
                            array('Не удаётся подключиться к серверу.', 'Проверьте подключение к сети Интернет.')));

                }

//                switch ($st_type) {
//                    case "hls":
//                        $url = $doc->hls;
//                        break;
//                    case "local":
//                        $url = $doc->local;
//                        break;
//                    case "local_low":
//                        $url = $doc->local_low;
//                        break;
//                    default:
//                        throw new DuneException(
//                            'HTTP network error', 0,
//                            ActionFactory::show_error(
//                                true,
//                                'Ошибка связи',
//                                array('Не удаётся подключиться к серверу.', 'Проверьте подключение к сети Интернет.')));
//                }
                if ($archive_ts > 0) {
                    if (isset($this->products[$channel_id][$archive_ts])) {
                        $pid = $this->products[$channel_id][$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 I24HSettings::$MATRAS_URL;
            }
        } else {
            $channel = $this->get_channel($channel_id);
            if ($channel->get_streaming_url() == "passive") {
                // Возврат матраса
                return I24HSettings::$MATRAS_URL;
            } else {
                return "protected";
            }
        }
    }

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

        $url = sprintf(
            $this->session->get_api_server() . I24hConfig::EPG_URL_FORMAT,
            $channel_id,
            $day_start_ts,
            $day_start_ts + 24 * 3600,
            $this->session->get_token()
        );

        try {
            $doc = $this->session->api_call($url);
        } catch (Exception $e) {
            throw new DuneException(
                'HTTP network error', 0,
                ActionFactory::show_error(
                    true,
                    'Ошибка связи',
                    array('Не удаётся подключиться к серверу.', 'Проверьте подключение к сети Интернет.')));
        }
        $epg = array();
        foreach ($doc 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;
    }

}

?>
