<?php
defined('IN_WEB') or die('Include Error!');
/**
 *	信鸽推送相关
 */

class ModelPush{
    //定义安卓和苹果的sid列表
    private $_andriod_sid_list = [1,3,5,7,9,11,13];
    private $_ios_sid_list = [2]; //[2,4,6,8,10,12,14]

    private $_secretInfo = array(//1 安卓, 2 IOS, 3 繁体安卓, 4繁体苹果, 5英语安卓, 6英语苹果, 7 奥马哈安卓 , 8 奥马哈苹果, 9 安卓主包, 10 IOS主包
        1 => array(
            'accessId' => 2100261272,
            'accessKey' => 'AM2X5RW58G1Y',
            'secretKey' => '8c398daf1d21bd82b5dce7c5b3fc827c',
        ),
        2 => array(
            'accessId' => 2200261278,
            'accessKey' => 'I7M9P63E6HFG',
            'secretKey' => 'cadb5e71d82d36f1724b72e2e640ae9f',
        ),
        3 => array(
            'accessId' => 2100275920,
            'accessKey' => 'AW45I8V5IH6P',
            'secretKey' => 'e42a5548ceee8cd4f7e25ba529b3c5d0',
        ),
        4 => array(
            'accessId' => 2200275921,
            'accessKey' => 'IY1EW9C842KB',
            'secretKey' => '8b223ff44fc9f81e76347dcd3271a383',
        ),
        5 => array(
            'accessId' => 2100275923,
            'accessKey' => 'A72Y37VAYL1E',
            'secretKey' => 'c2f28a374a74ad09a7be9e659f9ce2aa',
        ),
        6 => array(
            'accessId' => 2200275924,
            'accessKey' => 'IW4H68U9FM2G',
            'secretKey' => '773b4e0198bc71d0f8af0269d0391a9b',
        ),
        7 => array(
            'accessId' => 2100278390,
            'accessKey' => 'A1B8GI9Y5P7C',
            'secretKey' => '884cdfd614afe4900d72b531b043da4d',
        ),
        8 => array(
            'accessId' => 2200278391,
            'accessKey' => 'I85FG1TH36MB',
            'secretKey' => 'f8830313cf646c77c652ec737c575f27',
        ),
        9 => array(
            'accessId' => 2100278549,
            'accessKey' => 'A718VKKJ7N9F',
            'secretKey' => '31955700823e92dda1b5e375de71c45d',
        ),
        10 => array(
            'accessId' => 2200278550,
            'accessKey' => 'IMZ7X9K627MB',
            'secretKey' => '6dee06eb4bbd4dfcdef30ca199988d14',
        ),
        11 => array(
            'accessId' => 2100278561,
            'accessKey' => 'AND65V648VQM',
            'secretKey' => 'e7d90b7c6a5dc1cd97e21e29c8df0a51',
        ),
        12 => array(
            'accessId' => 2200278562,
            'accessKey' => 'I335MWG3E7KR',
            'secretKey' => '10e6f492889b0fb3439d21950538bd27',
        ),
        13 => array(
            'accessId' => 2100279187,
            'accessKey' => 'ANK2XX6M869P',
            'secretKey' => 'd3e3cb309c205d8990bab60a641a1995',
        ),
        14 => array(
            'accessId' => 2200279190,
            'accessKey' => 'IS32S15YG8SD',
            'secretKey' => '8e5a3457eb2642b5252c25fb1b667331',
        ),
        17 => array(
            'accessId' => 2100295942,
            'accessKey' => 'AV57B1J73YKH',
            'secretKey' => '48d6a245fbfac2955fa6f61b09bdebc0',
        ),
        19 => array(
            'accessId' => 2100301866,
            'accessKey' => 'ATQ53K9RL42Q',
            'secretKey' => '2bf618f4fbb186b840eb1e7f23780b9b',
        ),
        20 => array(
            'accessId' => 2200298948,
            'accessKey' => 'I4EF2537CLHK',
            'secretKey' => '1f89fae1ea69ee62f3ee77c8a3d1ec49',
        )

    );

    private $_accessId = 0;
    private $_secretKey = 0;

    static $xingeApp = '';

    public function __construct()
    {
        $info = $this->_secretInfo[1] ?? $this->_secretInfo[9];
        $this->_accessId = $info['accessId'];
        $this->_secretKey = $info['secretKey'];
    }

    /**
     *	初始化
     */
    protected function initFile($device){
        include_once(PATH_LIB.'xg/XingeApp.php');
        $info = $this->_secretInfo[$device] ?? $this->_secretInfo[9];
        $this->_accessId = $info['accessId'];
        $this->_secretKey = $info['secretKey'];
    }

    /**
     * Notes:获取推送配置
     * User: wsc
     * Time: 2020/11/11 9:40
     * @param bool $db
     * @return array
     */
    public function getPushConf($db=false){
        $key = okeys::fasebasePushConf();
        $cache =oo::commonOprRedis('config')->hGetAll($key);
        if(empty($cache)||$db){
            $tb = otable::fasebasePushConf();
            $sql = "SELECT * FROM {$tb}";
            $arr = oo::commonOprDb('config')->getAll($sql,1);
            if(!empty($arr)){
                foreach ($arr as  $v){
                    $v['conf'] = json_decode($v['conf'],true);
                    $cache[$v['id']] = json_encode($v,256);
                }
                oo::commonOprRedis('config')->hMset($key,$cache);
            }
        }
        $cache = $cache?funs::getArrFromJsonArr($cache):[];
        return $cache;
    }
    /**
     *  不入队立即给单个玩家推送消息
     *	国内只有在玩家登录游戏切换到后台时候才能收到推送
     * @param $uid
     * @param $title
     * @param $content
     * @param array $argument
     * @param string $type
     * @return array|int
     * Created by: Owen
     * Created on: 2020/7/4 16:58
     */
    public function pushNewsToOne($uid, $title, $content, $argument = array(),$type = ''){
        $pushLock = oo::commonOprModel('member')->getUserSettingLock($uid);
        if(!empty($pushLock)){
            if(in_array('ALL',$pushLock)){
                return -100;
            }
            if(($type == "steal" || $type == "attack") && in_array('stealAndAttack',$pushLock)){
                return -100;
            }
        }
        $ret = $this->getPushTokenByUid($uid);
        if( $ret <= -1 ){
            return -100;
        }
        $token = $ret['token'];
        $sid = $ret['sid'];
        $ret = $this->pushNewsSingle($title, $content, $token, $sid, $argument);
        return $ret;
    }

    /**
     *  入队给单个玩家推送消息
     *	国内只有在玩家登录游戏切换到后台时候才能收到推送
     * @param $uid
     * @param $titleKey
     * @param $contentKey
     * @param array $langArg
     * @param string $type
     * @param array $pushArg
     * @return array|int
     * Created by: Owen
     * Created on: 2020/7/4 17:06
     */
    public function pushNews($uid,$titleKey,$contentKey,$langArg = [],$type = '',$pushArg = []){
        $pushLock = oo::commonOprModel('member')->getUserSettingLock($uid);
        if(!empty($pushLock)){
            if(in_array('ALL',$pushLock)){
                return -100;
            }
            if(($type == "steal" || $type == "attack") && in_array('stealAndAttack',$pushLock)){
                return -100;
            }
        }
        $ret = $this->getPushTokenByUid($uid);
        if( $ret <= -1 ||$ret['token']=='BLACKLISTED'){
            return -100;
        }
        $token = $ret['token'];
        $lang  = $ret['lang']?strtolower($ret['lang']):'en';
        $sid   = $ret['sid']??1;
        $title = oo::commonOprModel('lang')->getLang($lang,$titleKey);
        $content =  oo::commonOprModel('lang')->getLang($lang,$contentKey,$langArg);
        $label = explode('.',$titleKey);
        $label = end($label);
        $img   = "";
        $pushCfg = $this->getPushConf();
        $id    = 0;
        foreach ($pushCfg as $row){
            if($row['class'] == "other" && $row['type'] == $label){
                if(!empty($row['conf'][$lang]["title"])){
                    $title   = $row['conf'][$lang]["title"];
                    $content = $row['conf'][$lang]["content"];
                    $id      = $row['id'];
                    if(!empty($langArg) && is_array($langArg)){
                        foreach ($langArg as $key=>$row){
                            $content = str_replace("{{$key}}",$row,$content);
                        }
                    }
                    break;
                }
            }
        }
        if(in_array($id,[16])){
            $img = "https://spin.gworldtek.com/public/game/image/firebase/{$id}.jpg";
        }
        $ret = self::push($token,$title,$content,$pushArg,$sid,$label,$img);
        return $ret;
    }

    /**
     * Notes:根据消息id推送消息
     * User: wsc
     * Time: 2020/11/9 12:01
     * @param $nid int 需要推送的消息id
     * @param array $uidList 需要推送的玩家列表
     * @param array $pushArg 额外参数
     * @return array|int
     */
    public function pushNewsByNid($nid,$uidList=[],$pushArg = []){
        $ret = [];
        if(empty($uidList)){
            return -100;
        }
        $pushCfg = $this->getPushConf();
        $uInfos = $this->getPushTokenByUid($uidList);
        if(empty($uInfos)||!is_array($uInfos)){
            return -99;
        }
        $uInfos = array_column($uInfos,null,'uid');
        if(!empty($uInfos)&&!empty($pushCfg[$nid])){
            foreach ($uidList as $uid){
                if(!isset($uInfos[$uid]['token'])){
                    continue;
                }
                $lang = $uInfos[$uid]['lang']??'en';
                $token = $uInfos[$uid]['token'];
                $title = $pushCfg[$nid]['conf'][$lang]['title'];
                $content = $pushCfg[$nid]['conf'][$lang]['content'];
                $sid   = $ret['sid']??1;
                $ret[$uid] = self::push($token,$title,$content,$pushArg,$sid,"activity");
            }
        }
        return $ret;
    }

    public function pushNewsToMultUserLang($uidList = array(), $title, $content){
        $count = count($uidList);
        $p = 100;
        $pages = ceil($count/$p);
        for ($i = 1; $i <= $pages; $i++) {
            $s = ($i-1)*$p;
            $tempArr = array_slice($uidList, $s , $p);
            $tokenList = self::getPushMultByUids($tempArr);
            if (!$tokenList) {
                continue;
            }
            foreach ($tokenList as $tokenArr) {
                if(isset($title[$tokenArr['lang']])){
                    $titleTemp = $title[$tokenArr['lang']];
                }else{
                    $titleTemp = $title['en'];
                }
                if(isset($content[$tokenArr['lang']])){
                    $contentTemp = $content[$tokenArr['lang']];
                }else{
                    $contentTemp = $content['en'];
                }
                oo::commonOprModel('firebase')->sendToDevice($tokenArr['token'], $titleTemp, $contentTemp);
            }
        }
        return 1;
    }

    /**
     *	给单个玩家推送消息
     *	只有在玩家登录游戏时候才能收到推送
     */
    public function pushNewsSingle($title, $content, $token, $sid, $argument = array())
    {
        $ret = oo::commonOprModel('firebase')->sendToDevice($token, $title, $content, $argument);
        return $ret;
    }

    /**
     *	给多个玩家推送
     */
    public function pushNewsToMultUser($uidList = array(), $title, $content)
    {
        if (!is_array($uidList)) {
            return -1;
        }
        include_once(PATH_LIB.'xg/XingeApp.php');
        $count = count($uidList);
        $p = 20;
        $pages = ceil($count/$p);
        for ($i = 1; $i <= $pages; $i++) {
            $s = ($i-1)*$p;
            $tempArr = array_slice($uidList, $s , $p);
            $tokenList = $this->getPushMultTokenByUids($tempArr);
            if (empty($tokenList) || $tokenList < 0) {
                continue;
            }
            foreach ($tokenList as $sid => $tokenArr) {
                foreach ($tokenArr as $t) {
                    oo::commonOprModel('firebase')->sendToDevice($t, $title, $content);
                }
            }
        }
        return 1;
    }

    /**
     *	根据账号类型和设备发送推送
     *	$deviceType		1 安卓	2 苹果
     *	$accountType	1 游客 	0 FB
     */
    public function pushNewsToMultUserByAccount($deviceType = 1, $accountType = 1, $title, $content)
    {
        $this->initFile($deviceType);
        $table = otable::xg_push();
        $sql = " SELECT COUNT(uid) AS c FROM {$table} WHERE sid = {$deviceType} AND token != '0' ";
        $ret = oo::commonOprDb('common')->getOne($sql, 1);
        $count = intval($ret['c']);
        if( $count <= 0 ){
            return;
        }
        $limit = 30;
        $pages = ceil($count / $limit);
        for ($i = 1; $i <= $pages; $i++) {
            $page = ($i -1) * $limit;
            $sqlList = " SELECT uid, token FROM {$table} WHERE sid = {$deviceType} AND token != '0' LIMIT {$page}, {$limit} ";
            $list = oo::commonOprDb('common')->getAll($sqlList, 1);
            if (empty($list)) {
                continue;
            }
            //循环处理
            foreach ($list as $info) {
                $uid = $info['uid'];
                $token = $info['token'];
                $isVisitor = oo::commonOprModel('member')->isVistor($uid);
                if ($isVisitor != $accountType && $accountType != 2) {//账号类型不匹配
                    continue;
                }
                oo::commonOprModel('firebase')->sendToDevice($token, $title, $content);
            }
        }
    }

    /**
     * 根据语言推送
     * @param int $deviceType
     * @param int $accountType
     * @param $title
     * @param $content
     * Created by: Owen
     * Created on: 2019/12/19 16:03
     */
    public function pushNewsToMultUserByAccountLang($deviceType = 1, $accountType = 1, $title, $content){
        $this->initFile($deviceType);
        $table = otable::xg_push();
        $sql = " SELECT COUNT(uid) AS c FROM {$table} WHERE sid = {$deviceType} AND token != '0' ";
        $ret = oo::commonOprDb('common')->getOne($sql, 1);
        $count = intval($ret['c']);
        if( $count <= 0 ){
            return;
        }
        $limit = 30;
        $pages = ceil($count / $limit);
        for ($i = 1; $i <= $pages; $i++) {
            $page = ($i -1) * $limit;
            $sqlList = " SELECT * FROM {$table} WHERE sid = {$deviceType} AND token != '0' LIMIT {$page}, {$limit} ";
            $list = oo::commonOprDb('common')->getAll($sqlList, 1);
            if (empty($list)) {
                continue;
            }
            //循环处理
            foreach ($list as $info) {
                $uid   = $info['uid'];
                $token = $info['token'];
                $lang  = $info['lang'];
                $isVisitor = oo::commonOprModel('member')->isVistor($uid);
                if ($isVisitor != $accountType && $accountType != 2) {//账号类型不匹配
                    continue;
                }
                if(isset($title[$lang])){
                    $title = $title[$lang];
                }else{
                    $title = $title['en'];
                }
                if(isset($content[$lang])){
                    $content = $content[$lang];
                }else{
                    $content = $content['en'];
                }
                oo::commonOprModel('firebase')->sendToDevice($token, $title, $content);
            }
        }
    }

    /**
     * 之前全部推送泰语的
     *	每日自动推送兑换码
     *	每日9:30 和 12:30
     */
    public function autoPushExchangeOld()
    {
        $money = 15000;
        $limit = 1000;
        $day = 1;
        $ret = oo::commonOprModel('exchangecode')->createCode($money, $limit, $day, 1, 1);
        $arr = json_decode($ret, 1);
        if( $arr['code'] != 1 ){
            oo::logs()->todebug(array('ret' => $ret), 'autoPushExchangeErr.log');
        }
        $code = $arr['num'];//兑换码
        $titleArr = oo::getLang('exchange_pushTitle');//标题
        $contentArr = oo::getLang('exchange_pushContent');//内容数组
        $randNum = array_rand($contentArr);
        $title = $titleArr[$randNum];
        $content = $contentArr[$randNum];
        $content = str_replace('@', $code, $content);

        //推送
        include_once(PATH_LIB.'xg/XingeApp.php');
        $android_accessId = $this->_secretInfo[9]['accessId'];
        $android_secretKey = $this->_secretInfo[9]['secretKey'];

        $ios_accessId 	= $this->_secretInfo[2]['accessId'];
        $ios_secretKey = $this->_secretInfo[2]['secretKey'];

        $androidold_accessId = $this->_secretInfo[1]['accessId'];
        $androidold_secretKey = $this->_secretInfo[1]['secretKey'];

        XingeApp::PushAllAndroid($android_accessId, $android_secretKey, $title, $content, array('type' => 3, 'code' => $code));
        XingeApp::PushAllAndroid($androidold_accessId, $androidold_secretKey, $title, $content, array('type' => 3, 'code' => $code));
        XingeApp::PushAllIos($ios_accessId, $ios_secretKey, $content, XingeApp::IOSENV_PROD, array('type' => 3, 'code' => $code));

        oo::logs()->todebug(array('code' => $code), 'autoPushExchangeSuc.log');
    }

    /**
     *	后台自动推送
     */
    public function autpPushNewsToAll()
    {
        $key = 'AUTOPUSHNEWSTOALL';
        $ret = oo::commonOprRedis('common')->lPop($key);
        if (empty($ret)) {
            return;
        }
        $info = json_decode($ret, 1);
        //list($devicetype, $accounttype, $title, $content) = $info;
        $devicetype = $info['devicetype'];
        $accounttype = $info['accounttype'];
        $title = $info['title'];
        $content = $info['content'];
        oo::logs()->debug3(array('devicetype' => $devicetype, 'accounttype' => $accounttype,'title' => $title, 'content' => $content), 'pushNewsToMultUserByAccount.log');
        $this->pushNewsToMultUserByAccount($devicetype, $accounttype, $title, $content);
    }

    /**
     *	通过UID获取推送的token
     */
    public function getPushTokenByUid($uids = 0){
        $table = otable::xg_push();
        $ret =[];
        if(is_array($uids)){
            $uidsStr =implode(',',$uids);
            $sql = "SELECT * FROM {$table} WHERE uid in({$uidsStr})";
            $ret = oo::commonOprDb('common')->getAll($sql, 1);
        }else if($uids>0){
            $sql = "SELECT * FROM {$table} WHERE uid={$uids} LIMIT 1";
            $ret = oo::commonOprDb('common')->getOne($sql, 1);
        }
        if( empty($ret) ){
            return -1;
        }
        return $ret;
    }

    /**
     *	获取多个token
     */
    public function getPushMultTokenByUids($uidList = array(), $flag = 1)
    {
        if(empty($uidList) || !is_array($uidList)){
            return false;
        }
        $uidStr = implode(',', $uidList);
        $table = otable::xg_push();
        $sql = " SELECT token, sid FROM {$table} WHERE uid IN ({$uidStr}) ";
        $ret = oo::commonOprDb('common')->getAll($sql, 1);
        if( empty($ret) ){
            return -1;
        }
        $list = array();
        foreach ($ret as $value) {
            if(empty($value['token'])){
                continue;
            }
            $sid = $value['sid'];
            if($flag == 2){

                $list[] = $value['token'];
            }else{
                $list[$sid][] = $value['token'];
            }

        }
        return $list;
    }


    /**
     * 获取多个用户信息
     * @param array $uidList
     * @return array|bool
     * Created by: Owen
     * Created on: 2019/12/19 15:53
     */
    public function getPushMultByUids($uidList = array())
    {
        if(empty($uidList) || !is_array($uidList)){
            return false;
        }
        $uidStr = implode(',', $uidList);
        $table = otable::xg_push();
        $sql = " SELECT * FROM {$table} WHERE uid IN ({$uidStr}) ";
        $ret = oo::commonOprDb('common')->getAll($sql, MYSQLI_ASSOC);
        if(empty($ret) ){
            return false;
        }
        $list = array();
        foreach ($ret as $value) {
            $list[] = [
                'uid'  => $value['uid'],
                'token'=> $value['token'],
                'lang' => $value['lang'],
                'topic'=> $value['topic'],
                'accountType'=> $value['accountType'],
            ];
        }
        return $list;
    }


    /**
     *	给所有IOS设备发送推送
     */
    public function pushAllIosDevice($content)
    {
        //推送
        include_once(PATH_LIB.'xg/XingeApp.php');

        $ios_accessId 	= $this->_secretInfo[2]['accessId'];
        $ios_secretKey = $this->_secretInfo[2]['secretKey'];

        $ret = XingeApp::PushAllIos($ios_accessId, $ios_secretKey, $content, XingeApp::IOSENV_PROD);
        return $ret;
    }

    /**
     *	给android设备推送信息
     */
    public function pushAllAndroidDevice($title, $content)
    {
        //推送
        include_once(PATH_LIB.'xg/XingeApp.php');

        $android_accessId 	= $this->_secretInfo[1]['accessId'];
        $android_secretKey = $this->_secretInfo[1]['secretKey'];

        $ret = XingeApp::PushAllAndroid($android_accessId, $android_secretKey, $title, $content);
        return $ret;
    }

    /**
     *	老用户召回
     */
    public function recallbackuser()
    {
        $key = 'XGRECALLBACK';
        $info = oo::commonOprRedis('recall')->lPop($key);
        //$info = oo::commonOprRedis('recall')->lGetRange($key, 0, -1);
        if (empty($info)) {
            return false;
        }

        $arr = json_decode($info, 1);
        if (!is_array($arr)) {
            return false;
        }

        $id = $arr['id'];//表id
        $day = $arr['day'];//流失天数
        $title = $arr['title'];//推送标题
        $conent = $arr['conent'];//推送内容
        $devices = $arr['devices'];//推送设备

        $losetime = strtotime('-'.$day.' days');//流失时间

        //计算推送人数
        $table = otable::xg_push();
        $sqlSum = " SELECT COUNT(uid) AS s FROM {$table} ";
        $sumRs = oo::commonOprDb('common')->getOne($sqlSum, 1);
        $sum = intval($sumRs['s']);
        if ($sum <= 0) {
            return false;
        }

        //修改召回状态
        $pushTable = otable::recallback_push();//召回表
        $updatstatussql = " UPDATE {$pushTable} SET status = 2 WHERE id = {$id} LIMIT 1";
        oo::commonOprDb('common')->query($updatstatussql);

        $where = " WHERE sid IN ($devices) ";
        $page = 20;
        $pages = ceil($sum/$page);

        //统计发送玩家总数
        $pushNum = 0;
        for ($i=1; $i <= $pages; $i++) {
            $start = ($i - 1)*$page;
            $sql = "SELECT uid, token FROM {$table} {$where} LIMIT $start, $page";
            $list = oo::commonOprDb('common')->getAll($sql, 1);
            $uidList = array();
            foreach ($list as $tempVal) {
                array_push($uidList, $tempVal['uid']);
            }
            $userinfo = array();
            $userInfoRs = oo::commonOprModel('member')->getUserInfoMulti(array('keylist' => $uidList), $userinfo);

            //查询流失玩家
            if ($userInfoRs != 1) {
                continue;
            }

            //处理流失玩家
            $recallbackUidList = array();
            foreach ($userinfo as $tempInfo) {
                $lasttime = $tempInfo['lasttime'];
                $tempUid = $tempInfo['uid'];
                if ($lasttime >= $losetime) {
                    continue;
                }
                array_push($recallbackUidList, $tempUid);
            }

            if (empty($recallbackUidList)) {
                continue;
            }
            $pushNum += count($recallbackUidList);
            $this->pushNewsToMultUser($recallbackUidList, $title, $conent);//发送推送
            usleep(1000);
        }

        //更新召回数据库
        $endtime = time();
        $updateSql = "UPDATE {$pushTable} SET nums = {$pushNum}, status = 1, endtime = {$endtime} WHERE id = {$id} LIMIT 1";
        oo::commonOprDb('common')->query($updateSql);

        //记录数据库
        oo::logs()->debug3(array('id' => $id, 'pushNum' => $pushNum, 'endtime' => $endtime), 'pushRecallback.log');
    }


    /**
     * 更新用户的标签
     * @param $uid
     * @return array|bool
     */
    public function refreshTag($uid, $lang)
    {
        if(empty($uid)) {
            return false;
        }
        $ret = $this->getPushTokenByUid($uid);
        if($ret <= -1) {
            return false;
        }
        $sid = $ret['sid'];
        $tag = $sid.'-'.$lang;
        $token = $ret['token'];
        $res = $this->refreshTagByToken($tag, $token, $sid);

        return $res;
    }



    /**
     *   查询该token是否有标签
     *   1.如果有，判断是否和该传入标签一样。一样则不处理，否则删除存在的不一样的，写入当前传入标签
     *   2.没有，直接写入
     * @param $tag
     * @param $token
     * @return array
     */
    public function refreshTagByToken($tag, $token, $sid = 0)
    {
        if($sid) {
            $this->initFile($sid);
        }
        include_once(PATH_LIB.'xg/XingeApp.php');
        $push = new XingeApp($this->_accessId, $this->_secretKey);
        //查询当前token下的标签
        $ret = $push->QueryTokenTags($token);
        $existTag = false;
        if($ret['ret_code'] == 0  && !empty($ret['result'])) {
            $tokenPairList = [];
            foreach ($ret['result']['tags'] as $tv) {
                if($tv != $tag){
                    $tokenPairsDel = new TagTokenPair($tv, $token);
                    array_push($tokenPairList, $tokenPairsDel);
                }else {
                    $existTag = true;
                }
            }
            if(!empty($tokenPairList)) {
                //批量删除其他标签
                $ret = $push->BatchDelTag($tokenPairList);//删除该token下的标签
                oo::logs()->nodatedebug($tv.'resdel:'.json_encode($ret));
            }

        }

        if(!$existTag) {
            $tokenPairsSet = new TagTokenPair($tag, $token);
            $setTag = $push->BatchSetTag([$tokenPairsSet]);
            if($setTag['ret_code'] == 0) {
                return oo::res(1);
            }
            return oo::res(-1);
        }else {
            return oo::res(1);
        }
    }

    /**
     * 查询token下的标签
     * @param $token
     * @return array|mixed
     */
    public function QueryTokenTags($token, $sid=0)
    {
        if($sid) {
            $this->initFile($sid);
        }
        //推送
        include_once(PATH_LIB.'xg/XingeApp.php');
        $push = new XingeApp($this->_accessId, $this->_secretKey);
        $ret = $push->QueryTokenTags($token);
        return $ret;
    }

    /**
     * 推送所有安卓该语言的玩家
     * @param $lang
     * @param $message
     * @return bool
     */
    public function pushAllAndroidByLang($lang, $title, $content, $argument=array())
    {
        include_once(PATH_LIB.'xg/XingeApp.php');
        $sidList = $this->_andriod_sid_list;
        foreach ($sidList as $sid){
            $this->initFile($sid);
            $tag = $sid.'-'.$lang;
            //推送
            $ret = XingeApp::PushTagAndroid($this->_accessId, $this->_secretKey, $title, $content, $tag, $argument );
            if($ret['ret_code'] != 0) {
                oo::logs()->debug3('pushByTags:  tag:'.$tag.'  sid:'.$sid.'  ret:'.json_encode($ret), 'pushtag_error.php');
            }
        }

        //firebase推送
        $topic  = 'lang_'.$lang;
        $res = oo::commonOprModel('firebase')-> sendToTopic($topic, $title, $content, $argument);

        return true;
    }

    /**
     * 推送所有苹果该语言的玩家
     * @param $lang
     * @param $message
     * @return bool
     */
    public function pushAllIosByLang($lang, $title, $content, $argument=array())
    {
        $sidList = $this->_ios_sid_list;
        foreach ($sidList as $sid){
            $this->initFile($sid);
            $tag = $sid.'-'.$lang;
            //推送
            $ret = XingeApp::PushTagIos($this->_accessId, $this->_secretKey, $content, $tag, 1, $argument);
            if($ret['ret_code'] != 0) {
                oo::logs()->debug3('pushByTags:  tag:'.$tag.'  sid:'.$sid.'  ret:'.json_encode($ret), 'pushtag_error.php');
            }
        }
        return true;
    }

    /**
     * 安卓按标签推送
     * @param $sid
     * @param $lang
     * @param $title
     * @param $content
     * @param array $argument
     */
    public function pushAndroidByTag($sid, $lang, $title, $content, $argument=array())
    {
        $this->initFile($sid);
        $tag = $sid.'-'.$lang;
        //推送
        $ret = XingeApp::PushTagAndroid($this->_accessId, $this->_secretKey, $title, $content, $tag, $argument );
        if($ret['ret_code'] != 0) {
            oo::logs()->debug3('pushByTags:  tag:'.$tag.'  sid:'.$sid.'  ret:'.json_encode($ret), 'pushtag_error.php');
        }
    }

    /**
     * 苹果按标签推送
     * @param $sid
     * @param $lang
     * @param $content
     * @param array $argument
     */
    public function pushIosByTag($sid, $lang, $content, $argument=array())
    {
        $this->initFile($sid);
        $tag = $sid.'-'.$lang;
        //推送
        $ret = XingeApp::PushTagIos($this->_accessId, $this->_secretKey, $content, $tag, 1, $argument);
        if($ret['ret_code'] != 0) {
            oo::logs()->debug3('pushByTags:  tag:'.$tag.'  sid:'.$sid.'  ret:'.json_encode($ret), 'pushtag_error.php');
        }
    }


    /**
     * 根据语言推送
     * @param $titleKey
     * @param $contentKey
     * @param array $extraData
     * Created by: Owen
     * Created on: 2020/7/6 11:07
     */
    public function pushByLang($titleKey, $contentKey,$extraData = []){
        $titleConfig   = oo::commonOprModel('lang')->getAllLang($titleKey);
        $contentConfig = oo::commonOprModel('lang')->getAllLang($contentKey);
        foreach ($titleConfig as $lang=>$value){
            oo::commonOprModel('firebase')->sendToTopic(okeys::FireBaseTopic($lang), $value, $contentConfig[$lang],$extraData);
        }
    }

    /**
     * 根据订阅主题推送
     * @param int $deviceType
     * @param int $accountType
     * @param $title
     * @param $content
     * Created by: Owen
     * Created on: 2020/3/23 15:13
     */
    public function pushByTopicClassLang($deviceType = 1, $accountType = 1, $title, $content){
        $table = otable::xg_push();
        $firebaseTopic = okeys::FireBaseTopic();
        $sql = "SELECT COUNT(uid) AS c FROM {$table} WHERE topic LIKE '%{$firebaseTopic}%' AND token != '0' AND sid={$deviceType}";
        if($accountType != 2){
            $sql .= " AND accountType={$accountType}";
        }
        $ret = oo::commonOprDb('common')->getOne($sql, 1);
        $count = intval($ret['c']);
        if( $count <= 0 ){
            return;
        }
        if($count != 1){
            return;
        }
        $limit = 100;
        $pages = ceil($count / $limit);
        for ($i = 1; $i <= $pages; $i++) {
            $page = ($i -1) * $limit;
            $sqlList = "SELECT * FROM {$table} WHERE topic LIKE '%{$firebaseTopic}%' AND sid = {$deviceType} AND token != '0'";
            if($accountType != 2){
                $sqlList .= " AND accountType={$accountType}";
            }
            $sqlList .=" LIMIT {$page}, {$limit} ";
            $list = oo::commonOprDb('common')->getAll($sqlList, 1);
            if (empty($list)) {
                continue;
            }
            $push = [];
            foreach ($list as $info) {
                $push[$info['lang']][] = $info['token'];
            }
            foreach ($push as $key=>$row){
                if(isset($title[$key])){
                    $title = $title[$key];
                }else{
                    $title = $title['en'];
                }
                if(isset($content[$key])){
                    $content = $content[$key];
                }else{
                    $content = $content['en'];
                }
                foreach ($row as $token){
                    oo::commonOprModel('firebase')->sendToDevice($token, $title, $content);
                }
            }
        }
    }

    /**
     * 推送入队
     * @param $token
     * @param $title
     * @param $content
     * @param $data
     * @param $sid
     * @return bool
     * Created by: Owen
     * Created on: 2020/3/23 16:18
     */
    public function push($token,$title,$content,$data = [],$sid = 1,$label = "",$img = ""){
        if(strlen($token) < 100){
            return false;
        }
        return oo::commonOprRedis('common')->rpush(okeys::FireBaseList(),json_encode([
            'token'   => $token,
            'title'   => $title,
            'content' => $content,
            'data'    => $data,
            'sid'     => $sid,
            'label'   => $label,
            'img'     => $img,
        ]));
    }

    /**
     * 推送出队
     * @param int $length
     * @return array
     * Created by: Owen
     * Created on: 2020/3/23 14:55
     */
    public function pop($length = 500){
        $key = okeys::FireBaseList();
        $ret  = oo::commonOprRedis('common')->lGetRange($key,0,$length);
        $return = [];
        foreach ($ret as $row){
            $return[] = json_decode($row,true);
        }
        oo::commonOprRedis('common')->lTrim($key,$length,-1);
        return $return;
    }

    /**
     * 定时推送
     * Created by: Owen
     * Created on: 2020/3/23 16:17
     */
    public function fireBasePushByRedisList(){
        $ret = self::pop();
        $path = "FireBasePush/".date('Ymd').'/';
        foreach ($ret as $row){
            try{
                oo::commonOprModel('firebase')->sendToDevice($row['token'], $row['title'], $row['content'], $row['data']??[],$row['sid']??1);
            }catch (Exception $exception){
                oo::logs()->debug5(['message'=>$exception->getMessage(),"time"=>time()],'FireBasePush.log',$path);
                continue;
            }
        }
    }

    /**
     * 排行榜活动Firebase推送
     * @return bool
     * Created by: Owen
     * Created on: 2020/7/4 18:57
     */
    public function rankFirebasePush(){
        if(oo::commonOprRedis('Activity')->get(okeys::ActivityRankPushLock("PUSH")) && !oo::commonOprRedis('Activity')->get(okeys::ActivityRankPushLock("PUSHED"))){
            $activity = oo::commonOprRedis('common')->hGetAll(okeys::Activity());
            if(empty($activity)){
                return false;
            }
            $isOnLine = false;
            $activityName = "";
            foreach ($activity as $key=>$row) {
                $temp = explode('#', $key);
                if ($temp[0] == 13) {
                    $temp = json_decode($row,true);
                    if(time() < $temp['reward_time']){
                        return false;
                    }
                    $isOnLine = true;
                    $activityName = $temp['activityName'];
                    break;
                }
            }
            if(!$isOnLine){
                return false;
            }
            $maxRoomId  = oo::commonOprModel('activity')->getRankCurMaxRoomId();

            //消息队列推送到不同服务器节点
            oo::commonOprModel('workerman')->pushFun('push', 'rankFirebaseCirclePush', [$activityName, $maxRoomId]);
        }
    }

    /**
     * 通知当前节点排行榜活动Firebase推送
     */
    public function rankFirebaseCirclePush($activityName, $maxRoomId){
        $online = oo::commonOprModel('workerman')->getAllUidList();
        for ($i=1;$i<=$maxRoomId;$i++){
            $users  = oo::commonOprModel('activity')->getRankRoomUsers($i);
            $pushUser = array_diff($users,$online);
            foreach ($pushUser as $uid){
                if(!oo::commonOprRedis('Activity')->hGet(okeys::RewardedAcRank(),$uid)){
                    $randId = oo::commonOprModel('activity')->getCurUserRank($uid);
                    if($randId !== false){
                        oo::commonOprRedis('Activity')->hSetNx(okeys::ActivityRankPushData(),$uid, $randId + 1)
                        && !IS_DEBUF && oo::commonOprModel('push')->pushNews($uid, 'push.title.activityRank','push.title.activityRank',[],'',['id'=>3,'content'=>0]);
                    }
                }
            }
        }
        oo::commonOprRedis('Activity')->expire(okeys::ActivityRankPushData(),oo::redisRandomExpire(3*24*60*60));
        oo::commonOprRedis('Activity')->setex(okeys::ActivityRankPushLock('activityName'),$activityName,oo::redisRandomExpire(3*24*60*60));
        oo::commonOprRedis('Activity')->setex(okeys::ActivityRankPushLock("PUSHED"),1,oo::redisRandomExpire(3*24*60*60));
    }

    /**
     * 新增等级推送
     * Created by: Owen
     * Created on: 2020/7/29 18:31
     */
    public function updateCurMaxLevel(){
        if(!IS_DEBUF && oo::commonOprRedis('common')->delete(okeys::UpdateCurMaxLevelPush())){
            $curMaxLevel = oo::commonOprModel('config')->getCurMaxLevel();
            $downLevel   = oo::commonOprModel('readconfig')->getSysCon('UpdateMaxLevel','downLevel') ?? 10;
            $actionLevel = max($curMaxLevel - $downLevel,90);
            $tb  = otable::gh_gameserver();
            $sql = "SELECT mid FROM {$tb} WHERE levelId > {$actionLevel}";
            $ret = oo::commonOprDb('common')->getAll($sql,MYSQLI_ASSOC);
            if(!empty($ret)){
                $uidArr = implode(',',array_column($ret,'mid'));
                $tb  = otable::xg_push();
                $sql = "SELECT * FROM {$tb} WHERE uid IN ({$uidArr})";
                $ret = oo::commonOprDb('common')->getAll($sql,MYSQLI_ASSOC);
                if(!empty($ret)){
                    $langContent = oo::commonOprModel('readconfig')->getSysCon('UpdateMaxLevel','push');
                    $langContent = json_decode($langContent,true);
                    foreach ($ret as $row){
                        self::push($row['token'],$langContent[$row['lang']]['title'],$langContent[$row['lang']]['content'],[],$row['sid'],"maxLevel");
                    }
                }
            }
        }
    }

    /**
     * 奖励定时推送
     * Created by: Owen
     * Created on: 2021/3/16 15:20
     */
    public function CrontabPush(){
        $pushList = [
            "FreeBar"  =>"freeBar",
            "TurnTable"=>"turnTable",
        ];
        foreach ($pushList as $type=>$langKey){
            $ret = oo::commonOprRedis('Usercache')->zRangeByScore(okeys::PushCrontab($type),0,time(),['withscores'=>true]);
            foreach ($ret as $uid=>$time){
                $this->pushNews($uid,"push.title.".$langKey,"push.content.".$langKey,[],$langKey);
                oo::commonOprRedis('Usercache')->zDelete(okeys::PushCrontab($type),$uid);
            }
        }
    }

    public function vipPush(){
        $tb  = otable::userinfo();
        $curTime = time();
        $ret = oo::commonOprDb('common')->getAll("SELECT uid FROM {$tb} WHERE vip=1 AND vip_expire>{$curTime}",MYSQLI_ASSOC);
        $uidArr = array_column($ret,"uid");
        foreach ($uidArr as $uid){
            $this->pushNews($uid,"push.title.vip","push.content.vip",[],"vip");
        }
    }
}
?>
