<?php

/**
 * 直播
 * junshi
 * 2020-4-3 17:00:13
 */

include LIB_PATH.'qiniu'.DS.'lib'.DS.'Pili_v2.php';

class liveController extends baseController {

    //公共参数
    private $ak;                 //Access Key
    private $sk;                 //Secret Key200
    private $hubName;            //空间名称
    //域名地址
    private $rtmp_push;          //RTMP推流
    private $rtmp_play;          //RTMP播放
    private $hls_play;           //HLS播放userOpenLive
    private $hdl_play;           //HDL播放
    private $cover;              //直播封面/截图
    private $choose_play;        //点播
    private $main_key;           //防盗链主密钥
    private $fu_key;             //防盗链副密钥

    //构造函数查询出所需数据
    public function __construct()
    {
        parent::__construct("BaseController");

        //查询验证平台信息
        $token = GetHeader();
        $tokenArray = unserialize($this->common->decryptByqingmiphp($token));
        $app_key = $tokenArray["appkey"];
        $platform = (new platformModule())->getInfoByAppKey($app_key);
        if (empty($platform)){
            returnFail([],getcodestr(4001),4001);
        }

        //公共参数
        $this->ak = $platform["access_key"];
        $this->sk = $platform["secret_key"];
        $this->hubName = $platform["hub_name"];
        $this->rtmp_push = $platform["rtmp_push"];
        $this->rtmp_play = $platform["rtmp_play"];
        $this->hls_play = $platform["hls_play"];
        $this->hdl_play = $platform["hdl_play"];
        $this->cover = $platform["cover"];
        $this->choose_play = $platform["choose_play"];
        $this->main_key = $platform["main_key"];
        $this->fu_key = $platform["fu_key"];
        $this->hubName = $platform["hub_name"];

    }

    /**
     * 创建hub
     * parameter: ak、sk、hubName
     * return hub
     */
    public function createHubAction(){
        $mac = new Qiniu\Pili\Mac($this->ak, $this->sk);
        $client = new Qiniu\Pili\Client($mac);
        $hub = $client->hub($this->hubName);
        return $hub;
    }

    /**
     * 获取stream
     * parameter: streamKey 流名称
     * return： stream
     */
    public function getStreamAction($streamKey){
        //获取hub
        $hub = $this->createHubAction();
        $stream = $hub->stream($streamKey);
        return $stream;
    }

    /**
     * 创建stream
     * parameter：streamKey 流名称
     * return：res 不会重复创建
     */
    public function createStreamAction($streamKey){
        $hub = $this->createHubAction();
        $hub->create($streamKey);
    }

    /**
     * 获取stream info
     * parameter：streamKey 流名称
     * return：res 不会重复创建
     */
    public function getStreamInfoAction($streamKey){
        $hub = $this->createHubAction();
        $stream = $hub->stream($streamKey);
        $res = $stream->info();
        return $res;
    }

    /**
     * 列出所有流
     * parameter: prefix 流前缀=空间名称、limit取出的个数
     * return: res[keys 流列表]
     */
    public function listStreamsAction($prefix,$limit=999999){
        //获取hub
        $hub = $this->createHubAction();
        $res = $hub->listStreams($prefix, $limit, "");
        return $res;
    }

    /**
     * 列出正在直播的流
     * parameter: prefix 流前缀=空间名称、limit取出的个数
     * return: res[keys 流列表]
     */
    public function listLiveStreamsAction($prefix,$limit=999999){
        //获取hub
        $hub = $this->createHubAction();
        $res = $hub->listLiveStreams($prefix, $limit, "");
        return $res;
    }

    /**
     * 批量列出正在直播的流
     * parameter: prefix 流前缀=空间名称、limit取出的个数
     * return: res[keys 流列表]
     */
    public function batchLiveStreamsAction($prefix){
        $hub = $this->createHubAction();
        $resp = $hub->batchLiveStatus(array($prefix, "foo", "bar"));
        return $resp["items"];
    }

    /**
     * 获取直播状态
     * parameter: streamKey
     * return: status
     * 包含error 说明没在直播
     */
    public function getLiveStatusAction($streamKey){
        $hub = $this->createHubAction();
        $stream = $hub->stream($streamKey);
        $status = $stream->liveStatus();
        return $status;
    }

    /**
     * 启用流
     * 启用之后返回状态
     * parameter: streamKey
     * return: status
     */
    public function enableStreamAction($streamKey){
        $hub = $this->createHubAction();
        $stream = $hub->stream($streamKey);
        $stream->enable();
        $status = $stream->liveStatus();
        return $status;
    }

    /**
     * 禁用流
     * 启用之后返回状态
     * parameter:
     * streamKey
     * time 时间戳, 在这之前流均不可用
     * return: status
     */
    public function disableStreamAction($streamKey,$time){
        $hub = $this->createHubAction();
        $stream = $hub->stream($streamKey);
        $stream->disable($time);
        $status = $stream->liveStatus();
        return $status;
    }

    /**
     * 保存直播数据
     * parameter:
     * streamKey 流
     * options 参数，详情参考 $stream->saveas()
     */
    public function savesStreamAction($streamKey,$options){
        $hub = $this->createHubAction();
        $stream = $hub->stream($streamKey);
        $res = $stream->saveas($options);
        return $res;
    }

    /**
     * 查询推流历史
     * parameter:
     * streamKey 流
     * start 开始时间，默认0 不限制
     * end 结束时间，默认0 不限制
     * return: records 返回开始时间与结束时间
     */
    public function getStreamHistoryAction($streamKey,$start = 0,$end = 0){
        $hub = $this->createHubAction();
        $stream = $hub->stream($streamKey);
        $records = $stream->historyActivity($start, $end);
        return $records["items"];
    }

    /**
     * 保存直播截图
     * parameter：
     * streamKey 流
     * options 条件
     * return res[fname] 文件名称
     */
    public function saveSnapshotAction($streamKey,$options = null){
        $hub = $this->createHubAction();
        $stream = $hub->stream($streamKey);
        $res = $stream->snapshot($options);
        return $res;
    }

    /**
     * 更改流的实时转码规格
     * parameter:
     * streamKey 流
     * before 之前码率
     * after 之后码率
     */
    public function updateConvertsAction($streamKey,$before,$after){
        $hub = $this->createHubAction();
        $stream = $hub->stream($streamKey);
        $stream->updateConverts(array($before, $after));
        $info = $stream->info();
        return $info;
    }

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

    /**
     * 获取RTMP推流地址
     * parameter:
     * hub_name     空间名称
     * streamKey    流名称
     * time         地址有效时间 单位秒 默认3600
     * return: url  推流地址
     */
    public function getRTMPPushAction(){
        //获取有效时间
        $time = $this->common->Post("time");
        //获取直播流
        $user_info = (new userModule())->getUserInfoByToken();
        $streamKey = $this->hubName.$user_info["number"];
        //执行创建流
        $this->createStreamAction($streamKey);
        $time = !empty($time)?$time:3600;
        $url = Qiniu\Pili\RTMPPublishURL($this->rtmp_push, $this->hubName, $streamKey, $time, $this->ak, $this->sk);
        returnSuccess($url,getcodestr(200),200);
    }

    /**
     * 获取RTMP直播地址
     * parameter:
     * hub_name     空间名称
     * streamKey    流名称
     * time         防盗链有效时间，默认5分钟
     * return: url  推流地址
     */
    public function getRTMPPlayAction(){
        //获取有效时间
        $time = $this->common->Post("time");
        //获取直播流
        $user_info = (new userModule())->getUserInfoByToken();
        $streamKey = $this->hubName.$user_info["number"];
        $time = !empty($time)?$time:300;  //防盗链有效时间
        $url = Qiniu\Pili\RTMPPlayURL($this->rtmp_play, $this->hubName, $streamKey);
        $path = "/".$this->hubName."/".$streamKey;  //兑换防盗链
        $url_final = $this->getPlaySignAction($url,$path,$time);
        returnSuccess($url_final,getcodestr(200),200);
    }

    /**
     * 获取HLS直播地址
     * parameter:
     * hub_name     空间名称
     * streamKey    流名称
     * time         防盗链有效时间，默认5分钟
     * return: url  推流地址
     */
    public function getHLSPlayAction(){
        //获取有效时间
        $time = $this->common->Post("time");
        //获取直播流
        $user_info = (new userModule())->getUserInfoByToken();
        $streamKey = $this->hubName.$user_info["number"];
        $time = !empty($time)?$time:300;  //防盗链有效时间
        $url = Qiniu\Pili\HLSPlayURL($this->hls_play, $this->hubName, $streamKey);
        $path = "/".$this->hubName."/".$streamKey.".m3u8";  //兑换防盗链
        $url_final = $this->getPlaySignAction($url,$path,$time);
        returnSuccess($url_final,getcodestr(200),200);
    }

    /**
     * 获取HDL直播地址
     * parameter:
     * hub_name     空间名称
     * streamKey    流名称
     * time         防盗链有效时间，默认5分钟
     * return: url  推流地址
     */
    public function getHDLPlayAction(){
        //获取有效时间
        $time = $this->common->Post("time");
        //获取直播流
        $user_info = (new userModule())->getUserInfoByToken();
        $streamKey = $this->hubName.$user_info["number"];
        $time = !empty($time)?$time:300;  //防盗链有效时间
        $url = Qiniu\Pili\HDLPlayURL($this->hdl_play, $this->hubName, $streamKey);
        $path = "/".$this->hubName."/".$streamKey.".flv";  //兑换防盗链
        $url_final = $this->getPlaySignAction($url,$path,$time);
        returnSuccess($url_final,getcodestr(200),200);
    }

    /**
     * 获取截图直播地址
     * parameter: streamKey
     * return: url
     */
    public function getCoverAction(){
        //获取直播流
        $user_info = (new userModule())->getUserInfoByToken();
        $streamKey = $this->hubName.$user_info["number"];
        $url = Qiniu\Pili\SnapshotPlayURL($this->cover, $this->hubName, $streamKey);
        returnSuccess($url,getcodestr(200),200);
    }

    //获取直播防添加盗链后的播放地址
    public function getPlaySignAction($url,$path,$time = 60 * 5){
        $t = dechex(time() + $time);   //有效时间5分钟
        $s = $this->main_key.$path.$t;
        $sign = strtolower(md5($s));
        $url_final = $url."?sign=".$sign."&t=".$t;
        return $url_final;
    }

    //获取推流地址
    public function getRTMPPush($streamKey){
        //执行创建流
        $this->createStreamAction($streamKey);
        $time = !empty($streamKey["time"])?$streamKey["time"]:3600;
        $url = Qiniu\Pili\RTMPPublishURL($this->rtmp_push, $this->hubName, $streamKey, $time, $this->ak, $this->sk);
        return $url;
    }

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

    /**
     * 贡献榜
     */
    public function getContributionListAction(){
        $request = Request::unsetRoute()->all();
        $contributionList = (new userGiftLogModule())->getContributionList($request["user_number"]);
        return $contributionList;
    }

    /**
     * 获取直播类型
     * return $type 类型
     */
    public function getLiveTypeAction(){
        $type = (new liveTypeModule())->getAllBySort();
        returnSuccess($type,getcodestr(200),200);
    }

    /**
     * 获取直播列表（获取热门、按类型获取）
     * parameter
     * is_hot   是否热门
     * type 直播类型id
     *
     */
    public function getOnLiveListAction(){
        $request = Request::unsetRoute()->all();
        //参数验证
        $userLiveLogModel = new userLiveLogModule();
        $res = $userLiveLogModel->verGetOnLiveList($request);
        $userModule = new userModule();
        $user = $userLiveLogModel->getUserInfoByToken();
        //参数验证通过
        if ($res){
            //组装查询条件
            $where = "live_type = {$res['live_type']}";
            $order = "user_num desc,create_time desc";

            //热门与非热门
            if ($res["hot"] == 1 || $res["hot"] == 2){
                $where .= " and is_hot = {$res['hot']}";
            }

            //最新
            if ($res["hot"] == 3){
                $order = "create_time desc,user_num desc";
            }

            //关注
            if ($res["hot"] == 4){
                //查询用户关注主播
                $user_shielding = (new userShieldingModule())->where(['user_number'=>$user["number"],'type'=>2])->all();
                $shielding_numbers = [];
                foreach ($user_shielding as &$v){
                    $shielding_numbers[] = $v["usered_number"];
                }
                if (!empty($shielding_numbers)){
                    $shielding_numbers_str = implode(",",$shielding_numbers);
                    $where .= " and user_number in ($shielding_numbers_str)";
                }else{
                    $where .= " and 1 != 1";
                }
            }

            //直播类型
            if (!empty($res["type"])){
                $where .= " and type_id = {$res['type']}";
            }

            //页码
            $offset = ($res["page"] * 1 - 1) * $res['limit'];

            //查询数据
            $userLiveLog = $userLiveLogModel
                ->where($where)
                ->orderBy("user_num desc,create_time desc")
                ->limit($offset, $res["limit"])
                ->orderBy($order)
                ->all();
            $num = $userLiveLogModel
                ->where($where)
                ->count();

            //查询用户信息，组装room_id
            foreach ($userLiveLog as $k => $v){
                $user_info = $userModule->getUserInfoByNumber($v['user_number']);
                $userLiveLog[$k]['room_id'] = $user_info['id'];
            }

            //返回数据
            $data['list'] = $userLiveLog;
            $data['total'] = $num;
            returnSuccess($data,getcodestr(200),200);
        }
    }

    function getcityAction($ip) {
        // 获取当前位置所在城市
        $content = file_get_contents("http://api.map.baidu.com/location/ip?ak=2TGbi6zzFm5rjYKqPPomh9GBwcgLW5sS&ip={$ip}&coor=bd09ll");
        $arr = json_decode($content,true);
        return $arr;
    }

    /**
     * 发起直播
     * parameter:
     * title 标题
     * cover 封面图
     * type 类型
     */
    public function userOpenLiveAction(){
        $ip = $_SERVER['REMOTE_ADDR'];
        $request = Request::unmeaning()->all();
        $userModule = new userModule();
        $user_info = $userModule->getUserInfoByToken();
        //验证用户信息
        $res = $userModule->verOpenLive($user_info,$request);
        //数据验证成功,生成直播数据
        if ($res){
            //获取推流地址
//            $streamKey = $this->hubName.$user_info["number"];
//            $url = $this->getRTMPPush($streamKey);
            $url = $request["url"];
            //初始化直播数据
            $data = [
                "user_number" => $user_info["number"],
                "title" => $request["title"],
                "img" => $request["cover"],
                "url" => $url,      //推流地址
                "type_id" => $request["type"],
                "is_hot" => 1,      //默认热门
                "money" => 0,       //印币收益
                "diamond" => 0,     //钻石收益
                "user_num" =>0,     //实际观看人数
                "usered_num" =>0,   //显示人数
                "warning" =>0,      //显示人数
                "live_type" =>1,    //直播中
                "is_offline" =>2,   //默认在线
                "hot" =>0,          //默认排序
                "top" =>0,          //置顶排序
                "create_time" =>date("Y-m-d H:i:s"),  //创建时间
                "update_time" =>date("Y-m-d H:i:s"),  //修改时间
                "ip" =>$ip,  //修改时间
            ];
            //生成直播记录
            $result = (new userLiveLogModule())->insert($data,false);
            $insert = (new commonModule('sl_ces'))->insert(['ces'=>$url]);
            if ($result){
                returnSuccess($url,getcodestr(200),200);
            }else{
                returnSuccess([],getcodestr(10001),10001);
            }
        }
    }

    /**
     * 结束直播[停止推流]
     */
    public function finishLiveAction(){

        //获取用户信息
        $userModule = new userModule();
        $user_info = $userModule->getUserInfoByToken();

        //查询直播信息
        $userLiveLogModule = new userLiveLogModule();
        $live_info = $userLiveLogModule->getOneByWhere(["live_type"=>1,"user_number"=>$user_info["number"]]);
        if (empty($live_info)){
            returnSuccess([],getcodestr(4010),4010);
        }

        //结束数据
        $data = [
            "live_type" => 2,
            "is_offline" => 1,
            "finish_time" => date("Y-m-d H:i:s"),
        ];

        $res = $userLiveLogModule->where(["id"=>$live_info["id"]])->update($data);
        if ($res){
            returnSuccess([],getcodestr(200),200);
        }else{
            returnSuccess([],getcodestr(10001),10001);
        }

    }

    /**
     * 编辑直播信息
     * parameter
     * cover 封面
     * title 标题
     */
    public function editOnLiveAction(){

        //获取信息
        $request = Request::unsetRoute()->all();

        //获取用户信息
        $userModule = new userModule();
        $user_info = $userModule->getUserInfoByToken();

        //查询直播信息
        $userLiveLogModule = new userLiveLogModule();
        $live_info = $userLiveLogModule->getOneByWhere(["live_type"=>1,"user_number"=>$user_info["number"]]);
        if (empty($live_info)){
            returnSuccess([],getcodestr(4010),4010);
        }

        $res = $userLiveLogModule->verEditOnLive($request);
        $result = $userLiveLogModule->where(["id"=>$live_info["id"]])->update($res);
        if ($result){
            returnSuccess([],getcodestr(200),200);
        }else{
            returnFail([],getcodestr(10001),10001);
        }

    }



    /**
     * 获取观众列表
     */

    /**
     * 直播热度
     * 1.主播开始直播分配一个基础热度，由主播等级决定
     * 2.增加热度的类型：新增观众、直播时长、新增弹幕、礼物赠送、贵宾
     * 3.会逐渐消失的热度：赠送礼物一段时间后
     *
     * parameter:
     * 主播编号
     * 类型
     * 状态：增加热度/降低热度
     * 热度值
     *
     */
    public function onLiveDegreeAction(){

    }

    /////////////== PK模块 ==////////////////

    /**
     * 获取PK类型
     */
    public function getPkTypeAction(){
        $pkType = (new pkTypeModule())->getAllBySort();
        returnSuccess($pkType,getcodestr(200),200);
    }

    /**
     * PK规则说明
     */
    public function getPkRulesAction(){
        $pkRules = (new pkRulesModule())->one();
        returnSuccess($pkRules,getcodestr(200),200);
    }

    /**
     * 对战记录
     */
    public function getPkLogAction(){
        $userModule = new userModule();
        $user_info = $userModule->getUserInfoByToken();
        $pkLogModules = new pkLogModule();

        //统计总场次
        $total_num = $pkLogModules->getUserPkTotal($user_info["number"]);

        //计算胜率
        $pk_log_win = $pkLogModules->getUserVictory($user_info["number"]);
        $win_pro = number_format(($pk_log_win / $total_num),2) * 100 ."%";

        //计算收益
        $total = $pkLogModules->totalProfit($user_info);

        //组装数据
        $data = [
            "total_num" => $total_num,                   //总场次
            "win_pro" => $win_pro,                       //胜率
            "total_profit" => $total["total_profit"],    //总收益
            "log" => $total["pk_log"],                   //历史战绩
        ];

        returnSuccess($data,getcodestr(200),200);

    }

    /**
     * 发起PK,创建连麦房间
     */
    public function createRoomAction(){
        $mac = new Qiniu\Pili\Mac($this->ak, $this->sk);
        $client = new Qiniu\Pili\RoomClient($mac);
        $resp = $client->createRoom("901", "testroom");
    }

    /**
     * PK匹配
     */

    /**
     * 结束PK
     */



}