<?php
/**
 *
 * 脚本
 *
 * @author ccw <31435391@qq.com>
 */
define("APPLICATION_PATH", realpath(dirname(__FILE__) . '/../../../')); //指向public的上一级
define("KEY_REDIS_PRE","PHPREDIS_SESSION:");
define("KEY_PRE","qm_:han_member:");
define("KEY_PRE_STORE","qm_:han_store:");
require APPLICATION_PATH . '/scripts/crontab/common.php';
header("Access-Control-Allow-Origin: *");
header('Access-Control-Allow-Method: *');
header('Access-Control-Allow-Headers: x-requested-with,content-type');
header('Content-type: application/json');
$conf = \Yaf\Registry::get('config')->get('redis.database.params');
$serv = new swoole_websocket_server("0.0.0.0", 9502);




// swoole 监听一个TCP端口来处理第三方客户端的消息请求
$tcp_server = $serv->addlistener('0.0.0.0', 9503, SWOOLE_SOCK_TCP);
$tcp_server->set(array(
    'open_length_check' => false,
    'package_length_type' => 'N',
    'package_length_offset' => 0,
    'package_max_length' => 8192,
    'open_eof_check'=> false,
    'package_eof' => "\r\n"
));
$serv->on('Open', function($server, $req) use($conf){
    $server->push($req->fd, responseJson(1,"conection","连接成功", ['method' => 'connection','status' => 1, 'error_code' => 0]));
});

function saveMessage(){

}
$serv->on('Message', function($server, $frame) use($conf){
    if($frame->data=='?'){
        $server->push($frame->fd,'!');

    }else{
        // redis 没有设置密码
        $redis=new Redis();
        $redis->connect($conf['host'], $conf['port']);
        if(!empty($conf['password'])){
            $redis->auth($conf['password']);
        }
        // echo $frame->data;
        echo $frame->data;
        echo 11111111111;
        $rev_data = json_decode($frame->data,true);
        //echo json_encode($rev_data);
        $method = isset($rev_data['method']) ? $rev_data['method'] : '';
        //echo $method;
        $key = isset($rev_data['key']) ? $rev_data['key'] : '';
        $key=isset($rev_data['data']['key'])?$rev_data['data']['key']:$key;
        if($method=='sendMsg'){
            $rev_data=$rev_data['data'];
            $realKey = KEY_REDIS_PRE.$key;
            $sessData=$redis->get($realKey);
//            $sessDataSpilt1=explode(';',$sessData);
//            $sessDataSpilt2=explode('|',$sessDataSpilt1[1]);
//            $sessDataSpilt3=explode(':', $sessDataSpilt2[1]);
//            $res= $sessDataSpilt3[1];
            $matchs=array();
            preg_match("/member_id\|i:(\d+)/i",$sessData,$matchs);
            $memberId= $matchs[1];
            $messageService=\Business\Message\MessageServiceModel::getInstance();
            $sendFd=$redis->hGet(KEY_PRE.$rev_data['toId'],'fd');
            $sendTime= $redis->hGet(KEY_PRE.$memberId,'sendTime');
            $diffTime=time()-$sendTime;
            if($diffTime==0){
                $async_login_data = [
                    'method'=>'sendMsg',
                    'status' => 0,
                    'message' => '一秒钟只能发一次消息',// eat drink play more and more
                    'data' => array(
                        'fd'=>$frame->fd,
                        'method'=>'sendMsg',
                    )
                ];
                $server->push($frame->fd,responseJson($async_login_data['status'],$async_login_data['method'],$async_login_data['message'], $async_login_data['data']));

            }else{
                if(!empty($memberId)){
                    $sendMessage['message']['type']=$rev_data['messageType'];
                    $strId=time().(string)$memberId;
                    $sendMessage['id']=(int)$strId;
                    $sendMessage['message']['title']=(isset($rev_data['messageTitle'])&&!empty($rev_data['messageTitle']))?$rev_data['messageTitle']:'';
                    $sendMessage['message']['content']=$rev_data['messageContent'];
                    $sendMessage['message']['url']= isset($rev_data['messageUrl'])?$rev_data['messageUrl']:'';
                    $sendMessage['message']['href']=isset($rev_data['messageHref'])?$rev_data['messageHref']:'';
                    $sendMessage['message']['price']=isset($rev_data['messagePrice'])?$rev_data['messagePrice']:'';
                    $sendMessage['message']['thumb']=isset($rev_data['messageThumb'])?$rev_data['messageThumb']:'';
                    $sendMessage['message']['gmtCreate']= time();
                    $sendMessage['fromId']=$memberId;
                    $sendMessage['fromUserId']=  $rev_data['fromUserId'];
                    $sendMessage['fromUserName']= $rev_data['fromUserName'];
                    $sendMessage['fromAvatar']= $messageService->getAvatar( $rev_data['fromType'],$rev_data['fromUserId']);
                    $sendMessage['fromType']= $rev_data['fromType'];
                    $sendMessage['toId']=  $rev_data['toId'];
                    $sendMessage['toUserId']=$rev_data['toUserId'];
                    $sendMessage['toUserName']=$rev_data['toUserName'];
                    $sendMessage['toType']= $rev_data['toType'];
                    if(!empty($sendFd)){
                        echo '发送fd:'.$sendFd;
                        if($sendFd!=$frame->fd){
                            $server->push($sendFd, responseJson(1,"fromMsg","success", $sendMessage));

                        }
                    }
                    echo 'afterSendFd:'.$sendFd;
                }
                //echo json_encode($sendMessage);
                //$redis->rPush("message_center",serialize($sendMessage));
                $redis->hSet(KEY_PRE.$memberId,'sendTime', time());
                $server->push($frame->fd, responseJson(1,"sendMsg","success", $sendMessage));
                $messageService->addMessage($sendMessage['fromId'],$sendMessage['fromUserId'],$sendMessage['fromUserName'],$sendMessage['fromType'],$sendMessage['message'],$sendMessage['toId'],$sendMessage['toUserId'],$sendMessage['toUserName'],$sendMessage['toType'],$sendMessage['id']);
                $sendMessage['message']=serialize($sendMessage['message']);
                $redis->rPush('push_center',serialize($sendMessage));
                $redis->hIncrBy(KEY_PRE.$rev_data['toId'],'unread_message_count',\Our\ApiConst::one);
            }
            $redis->close();
            unset($redis);
            unset($memberDb0Redis);
            // $messageService->unsetDb();
            unset($messageService);
            \Mysql\LinkMySQLModel::unsetDbConecet();
        }else{
            $realKey = KEY_REDIS_PRE.$key;
            $sessData=$redis->get($realKey);
//            $sessDataSpilt1=explode(';',$sessData);
//            $sessDataSpilt2=explode('|',$sessDataSpilt1[1]);
//            $sessDataSpilt3=explode(':', $sessDataSpilt2[1]);
            // $res= $sessDataSpilt3[1];
            $res=$sessData;
            //echo $res;
            $matchs=array();
            preg_match("/member_id\|i:(\d+)/i",$sessData,$matchs);//现在
            $storeMatchs=array();
            preg_match("/store_id\|i:(\d+)/i",$sessData,$storeMatchs);//现在
            // preg_match("/member_id\|i[^\d]{1,3}(\d+)/i",$res,$matchs);过去
            $memberId=$matchs[1];
            if(isset($storeMatchs[1]) && $storeMatchs[1]>0 ){
                $storeId=$storeMatchs[1];
            }else{
                $storeId=0;
            }
            echo "success:memberid=".$memberId.'login'."\n";
            $redis->expire($realKey,\Our\ApiConst::tenDaySecond);
            if($memberId==(int)$memberId){
                switch($method) {
                    case 'join':
                        $async_login_data = [
                            'method'=>'login',
                            'status' => 1,
                            'message' => "用户登录成功",// eat drink play more and more
                            'data' => array(
                                'fd'=>$frame->fd,
                                'method'=>$method,
                            )
                        ];
                        echo 'set:'.KEY_PRE.$memberId,'fd:'.$frame->fd."\r\n";
                        $redis->hSet(KEY_PRE.$memberId,'fd', $frame->fd);
                        if($storeId){
                            echo KEY_PRE_STORE.$storeId.'fd='.$frame->fd;
                            $redis->hSet(KEY_PRE_STORE.$storeId,'fd', $frame->fd);
                        }
                        $server->push($frame->fd,responseJson($async_login_data['status'],$async_login_data['method'],$async_login_data['message'], $async_login_data['data']));
                        $redis->close();
                        break;
                    default:
                        break;
                }
            }else{
                $async_login_data = [
                    'method'=>'login',
                    'status' => 0,
                    'message' => "用户授权失败",// eat drink play more and more
                    'data' => array(
                        'fd'=>$frame->fd,
                        'method'=>$method,
                    )
                ];
                $server->push($frame->fd,responseJson($async_login_data['status'],$async_login_data['method'],$async_login_data['message'], $async_login_data['data']));
                $server->close($frame->fd);
            }
        }

    }


});

/**
 * 接受 client 端信息推送,涉及问题
 * 1. 服务端认证、授权(安全)
 * 2. 推送消息落地(redis队列->MySQL)
 * 3. 推送客户端和消息中心交互, TCP
 * 4. 按照用户类型(channel)推送
 */
$tcp_server->on('connect', function($serv, $fd) use($conf){
    echo "Client:Connect\r\n";
});

/**
 * 接受 client 端信息推送,涉及问题
 * 1. 服务端认证、授权(安全)
 * 2. 推送消息落地(redis队列->MySQL)
 * 3. 推送客户端和消息中心交互, TCP
 * 4. 按照用户类型(channel)推送
 */
$tcp_server->on('receive', function($serv, $fd, $from_id, $data) use($conf) {
    // echo $data;
    //$data = json_decode($data, true);

//    if(empty($data['data']) && !isset($data['data'])){
//        $serv->send($fd, responseJson(1,"fail", ['method' => 'receive', 'error_code' => 1, 'status' => 0]));
//        $serv->close($fd);
//        return;
//    }
    if(empty($data) && !isset($data)){
        $serv->send($fd, responseJson(1,"fail", ['method' => 'receive', 'error_code' => 1, 'status' => 0]));
        $serv->close($fd);
        return;
    }
    // $s = json_encode($data['data']);
    echo $data;
    // 推送 存入redis、最后入库(MySQL)
    $redis=new Redis();
    $redis->connect($conf['host'], $conf['port']);
    if(!empty($conf['password'])){
        $redis->auth($conf['password']);
    }
    $key=trim($data,"\r\n");
    $data=$redis->get($key);
    $redis->delete($key);
    $data=json_decode($data,true);
    if(true) {
        $serv->send($fd, responseJson(1,"success", ['method' => 'receive', 'error_code' => 0, 'status' => 1]));
        $serv->close($fd);
        if(!isset($data['uid']) || empty($data['uid'])){
            foreach($data['data'] as $value){
                if(isset($value['type'])&&$value['type']>100){
                    $sendStoreFd=$redis->hGet(KEY_PRE_STORE.$value['storeId'],'fd');
                    if(!empty($sendStoreFd)){
                        if(!$value['message']){
                            $value['message']=new \stdClass();
                        }
                        $serv->push($sendStoreFd, responseJson(1,"fromMsg","success", $value));
                    }
                }else{
                    $async_data = $redis->rPush("message_center", serialize($value));
                    if($async_data){
                        $value['message']=unserialize($value['message']);
                        $sendFd=$redis->hGet(KEY_PRE.$value['toId'],'fd');
                        $redis->hIncrBy(KEY_PRE.$value['toId'],'unread_message_count',\Our\ApiConst::one);
                        if(!empty($sendFd)){
                            if(!$value['message']){
                                $value['message']=new \stdClass();
                            }
                            $serv->push($sendFd, responseJson(1,"fromMsg","success", $value));
                            $redis->hSet(KEY_PRE.$value['fromId'],'sendTime', time());
                        }
                    }
                }

            }
        }else{
            $async_data = $redis->rPush("message_center",serialize($data['data']));
            if($async_data){
                $sendFd=$redis->hGet(KEY_PRE.$data['data']['toId'],'fd');
                $data['data']['message']=unserialize($data['data']['message']);
                $redis->hIncrBy(KEY_PRE.$data['data']['toId'],'unread_message_count',\Our\ApiConst::one);
                if(!empty($sendFd)){
                    if(!$data['data']['message']){
                        $data['data']['message']=new \stdClass();
                    }
                    $serv->push($sendFd, responseJson($sendFd,"fromMsg","success", $data['data']));
                    $redis->hSet(KEY_PRE.$data['data']['fromId'],'sendTime', time());
                }
            }
        }

    } else {
        $serv->send($fd, responseJson(1,'fromMsg',"fail", ['method' => 'receive', 'error_code' => 110,'status' => 0]));
    }
    $redis->close();
    unset($redis);

});

$tcp_server->on('close', function ($serv, $fd) {
    echo "Client: Close.\n";
});

$serv->on('Close', function($server, $fd) use($conf){
    $key = 'user_'.$fd;
    $redis=new Redis();
    $redis->connect($conf['host'], $conf['port']);
    if(!empty($conf['password'])){
        $redis->auth($conf['password']);
    }
    $redis->hDel("client_list",$key);
    echo "connection close: ".$fd;
});

function responseJson($status = 1,$method, $message = '', $data = array()) {
    if(!$data['message']){
        $data['message']=new \stdClass();
    }
    $data = [
        'status' => $status,
        'method'=>$method,
        'message' => $message,
        'data' => $data,
    ];
    echo json_encode($data);
    return json_encode($data);
}
$serv->start();
