<?php
defined( 'IN_WEB') or die( 'Include Error!');
/**
 * 钻石相关
 */
class ModelDiamond
{

    CONST COINNOTENOUGH  = 4; //金币不足pid
    CONST SPINNOTENOUGH  = 5; //体力不足pid

    /**
     * 钻石商品gpid映射的groupid
     * @return array
     */
    public function getGroupWithGpid() {
        return [ 1 => 220, 2 => 221, 3 => 222, 4 => 223, 5 => 224, 6 => 225, ];
    }

    /**
     * 钻石积分获取兑换商城分组列表
     * @param int $groupId
     * @return array
     */
    public function getGroupsByScore($score) {
        //积分分组
        $scores = [
            220 => [
                [0, 100],
                [101, 10000],
            ],
            221 => [
                [0, 100],
                [10000, 9999999999],
            ],
            222 => [
                [0, 100],
                [101, 10000],
            ],
            223 => [
                [10000, 9999999999],
            ],
            224 => [
                [101, 10000],
            ],
            225 => [
                [10000, 9999999999],
            ]
        ];
        $arr = [];
        foreach($scores as $k => $v){
            foreach($v as $vv){
                if($score >= $vv[0] && $score <= $vv[1]){
                    $arr[] = $k;
                    break;
                }
            }
        }
        return $arr;
    }

    /**
     * 获取钻石商城兑换信息
     */
    public function getShopDiamondWithClient($uid) {
        $version = oo::commonOprModel('user')->getUserVersion($uid);
        if(oo::compareVersion($version,'1.7.7')){
            $shop = $this->getNewShopDiamond();
            $uExchanged = $this->getNewUserExchangeInfo($uid);
        }else{
            $shop = $this->getShopDiamond();
            $uExchanged = $this->getUserExchangeInfo($uid);
        }
        if(!oo::compareVersion($version,'1.8.4')){
            unset($shop[2237]);
            unset($shop[2238]);
            unset($shop[2239]);
        }
        $pStages = $arr = [];
        foreach($shop as $k => $v){
            if(!isset($pStages[$v['pid']])){
                $pStages[$v['pid']] = 0;
            }else{
                $pStages[$v['pid']] += 1;
            }
            $pInfo = empty($uExchanged[$v['pid']]) ? [] : $uExchanged[$v['pid']];
            if(oo::compareVersion($version,'1.7.7') && isset($pInfo[$pStages[$v['pid']]])){
                $pInfo = isset($pInfo[$pStages[$v['pid']]]) ? $pInfo[$pStages[$v['pid']]] : [];
            }
            if(!isset($arr[$v['pid']])){
                $expire = isset($pInfo['expire']) ? $pInfo['expire'] : 0;
                $stage = empty($pInfo['stage']) ? 0 : $pInfo['stage'];
                $buyTimes = empty($pInfo['buyTimes']) ? 0 : $pInfo['buyTimes'];
                if($expire && $expire < time()){ //cd过期了
                    $expire = $stage = $buyTimes = 0;
                }
                //每次都有cd，客户端只有最后一次展示cd
                if(oo::compareVersion($version,'1.7.7')){
                    $expire = $buyTimes < $v['times'] ? 0 : $expire;
                }else{
                    if($expire && !$this->checkIfLast($v['pid'], $pInfo, $version)){
                        $expire = 0;
                    }
                }

                $arr[$v['pid']] = [
                    'gid'      => $v['pid'],
                    'list'     => [],
                ];
                if(!oo::compareVersion($version,'1.7.7')){
                    $arr[$v['pid']]['stage'] = $stage;
                    $arr[$v['pid']]['buyTimes'] = $buyTimes;
                    $arr[$v['pid']]['expire']   = $expire;
                }
            }

            if(isset($v['gbaseReward']['props'])){
                $v['propId'] = $v['gbaseReward']['props'];
                $v['num'] = 1;
            }else{
                $v['gbaseReward'] = $this->getReward($uid, $v['gbaseReward']);
                $key = key($v['gbaseReward']);
                $key = $key == 'money' ? 'coins' : $key;
                $v['propId'] = $key;
                $v['num'] = current($v['gbaseReward']);
            }

            if(oo::compareVersion($version,'1.7.7')){
                if((!isset($pInfo['expire']) || $pInfo['expire'] < time())){
                    $v['expire'] = $v['buyTimes'] = 0;
                }else{
                    $v['expire'] = $pInfo['expire'];
                    $v['buyTimes'] = isset($pInfo['buyTimes']) ? $pInfo['buyTimes'] : 0;
                }
                $v['stage'] = $pStages[$v['pid']];
            }else{
                $v['expire'] = $v['gExpire'];
            }
            unset($v['gbaseReward'], $v['gExpire'], $v['stages']);
            $arr[$v['pid']]['list'][] = $v;
        }
        return array_values($arr);
    }

    /**
     * 获取玩家阶次兑换信息
     * @param int $uid
     * @param int $pid
     */
    public function getExchangedWithClient($uid, $pid, $stage, $version = '') {
        if(empty($version)){
            $version = oo::commonOprModel('user')->getUserVersion($uid);
        }
        if(oo::compareVersion($version,'1.7.7')){
            $info = $this->getNewUserExchangeInfo($uid, $pid);
            if(isset($info[$stage])){
                $info = $info[$stage];
            }else{
                $info = [];
            }
        }else{
            $info = $this->getUserExchangeInfo($uid, $pid);
        }
        if(empty($info)){
            $info = ['stage' => 0, 'buyTimes' => 0, 'expire' => 0];
        }
        if(oo::compareVersion($version,'1.7.7')){
            $shopArr = $this->getShopDiamondByPid($pid, $version);
            $gInfo = isset($shopArr[$stage]) ? $shopArr[$stage] : [];
            if(empty($gInfo) || $gInfo['times'] > $info['buyTimes']){
                $info['expire'] = 0;
            }
            $info['stage'] = $stage;
            $info['expire'] = (isset($info['expire']) && $info['expire'] > time()) ? $info['expire'] : 0;
        }else{
            if(empty($info['expire']) || !$this->checkIfLast($pid, $info, $version)){
                $info['expire'] = 0;
            }
        }

        return $info;
    }

    public function getShopDiamondByPid($pid = 0, $version = '1.7.3') {
        if(oo::compareVersion($version,'1.7.7')){
            $tmp = $this->getNewShopDiamond();
        }else{
            $tmp = $this->getShopDiamond();
        }
        $arr = [];
        foreach($tmp as $k => $v){
            if(!isset($arr[$v['pid']])){
                $arr[$v['pid']] = [];
            }
            $arr[$v['pid']][] = $v;
        }
        return isset($arr[$pid]) ? $arr[$pid] : [];
    }

    /**
     * 新版钻石兑换分3行显示
     * @param int $gid
     * @return array
     */
    public function getNewShopDiamond($gid = 0) {
        $arr = $this->getShopDiamond();
        $pid3Arr = $data = [];
        $end = end($arr);
        $stages3 = $end['stages'];
        $stages2 = 0;
        foreach($arr as $k => $v){
            if($v['pid'] == 3){ //pid3的结构有变更
                $v['pid'] = 2;
                $v['stages'] += $stages2;
                $pid3Arr[$k] = $v;
                continue;
            }
            if($v['pid'] == 2){
                empty($stages2) && $stages2 = $v['stages'];
                $v['stages'] = $v['stages'] + $stages3;
            }
            $data[$k] = $v;
        }
        $data = $data + $pid3Arr;
        if($gid){
            return !isset($data[$gid]) ? [] : $data[$gid];
        }
        return $data;
    }

    public function getShopDiamond($gid = 0) {
        $arr = oo::commonOprRedis("common")->hGetAll(okeys::shopDiamond());
        ksort($arr);
        $stages = [];
        if(empty($arr)){
            $tb = otable::diamondCrazy();
            $sql = "SELECT * FROM {$tb} WHERE pid IN(1, 2, 3,6)";
            $rs = oo::commonOprDb('common')->getAll($sql,1);
            $arr = [];
            foreach($rs as $k => $v){
                $v['gbaseReward'] = json_decode($v['gbaseReward'], true);
                $arr[$v['gid']] = $v;
                $stages[$v['pid']] = isset($stages[$v['pid']]) ? $stages[$v['pid']]+1 : 1;
            }
            //存redis
            foreach($arr as $k => $v){
                $v['stages'] = isset($stages[$v['pid']]) ? $stages[$v['pid']] : 0;
                $arr[$k] = $v;
                oo::commonOprRedis("common")->hSet(okeys::shopDiamond(), $k, json_encode($v));
            }
        }
        foreach($arr as $k => $v){
            $arr[$k] = is_array($v) ? $v : (array)json_decode($v, true);
        }
        if($gid){
            return !isset($arr[$gid]) ? [] : $arr[$gid];
        }
        return $arr;
    }

    /**
     * 获取下一次过期时间戳
     */
    public function getExpire() {
        $expire = strtotime(date('Y-m-d', strtotime('+1 days')));
        if(defined('IS_DEBUF') && IS_DEBUF){
            $h = date('H');
            if($h < 8){ //世界时间前一天
                $expire = strtotime(date('Y-m-d', time()))+8*3600;
            }else{
                $expire = strtotime(date('Y-m-d', strtotime('+1 days')))+8*3600;
            }
        }
        return $expire;
    }

    /**
     * 新版玩家钻石兑换记录
     * @param int $uid
     * @param int $pid
     * @return array
     */
    public function getNewUserExchangeInfo($uid, $pid = 0) {
        $arr = oo::commonOprRedis("user")->hGetAll(okeys::userDdiamond($uid));
        //最大过期时间,第二天0点
        $maxExpire = $this->getExpire();
        if($pid){
            $info = !empty($arr[$pid]) ? (array)json_decode($arr[$pid], true) : [];
            foreach($info as $k => $v){
                if($info[$k] && !isset($info[$k]['buyTimes'])){ //第一次直接重置
                    //$info[$k]['expire'] = time()-8*3600-1; //世界时间
                    oo::commonOprRedis("user")->delete(okeys::userDdiamond($uid));
                    return [];
                }
                if(!empty($info[$k]['expire']) && $info[$k]['expire'] > $maxExpire){
                    $info[$k]['expire'] = $maxExpire;
                }
                if($info[$k]['expire'] < time()){
                    $info[$k]['expire'] = $info[$k]['buyTimes'] = 0;
                }
            }
            return $info;
        }
        foreach($arr as $k => $v){
            $arr[$k] = (array)json_decode($v, true);
            //老版本的数据直接清除
            if($arr[$k] && (isset($arr[$k]['buyTimes']) || isset($arr[$k]['expire']))){
                oo::commonOprRedis("user")->delete(okeys::userDdiamond($uid));
                return [];
            }
            foreach($arr[$k] as $kk => $vv){
                if(!empty($arr[$k][$kk]['expire']) && $arr[$k][$kk]['expire'] > $maxExpire){
                    $arr[$k][$kk]['expire'] = $maxExpire;
                }
                if($arr[$k][$kk]['expire'] < time()){
                    $arr[$k][$kk]['buyTimes'] = $arr[$k][$kk]['expire'] = 0;
                }
            }
        }
        return $arr;
    }

    /**
     * 获取玩家当前商品钻石兑换阶次
     * @param int $uid
     * @param int $pid 钻石商品组id [1, 2, 3]
     * @return array
     */
    public function getUserExchangeInfo($uid, $pid = 0) {
        $arr = oo::commonOprRedis("user")->hGetAll(okeys::userDdiamond($uid));
        //最大过期时间,第二天0点
        $maxExpire = $this->getExpire();
        if($pid){
            $info = !empty($arr[$pid]) ? (array)json_decode($arr[$pid], true) : [];
            if($info && !isset($info['expire'])){
                $info['expire'] = 0; //世界时间
                oo::commonOprRedis("user")->hSet(okeys::userDdiamond($uid), $pid, json_encode($info));
            }
            if(!empty($info['expire']) && $info['expire'] > $maxExpire){
                $info['expire'] = $maxExpire;
            }
            return $info;
        }
        foreach($arr as $k => $v){
            $arr[$k] = (array)json_decode($v, true);
            //兼容前期redis没有设置expire问题
            if($arr[$k] && !isset($arr[$k]['expire'])){
                $arr[$k]['expire'] = 0; //世界时间
                oo::commonOprRedis("user")->hSet(okeys::userDdiamond($uid), $k, json_encode($arr[$k]));
            }
            if(!empty($arr[$k]['expire']) && $arr[$k]['expire'] > $maxExpire){
                $arr[$k]['expire'] = $maxExpire;
            }
        }
        return $arr;
    }

    public function getGroupIdByGid($gid) {
        $arr = $this->getShopDiamond($gid);
        if(empty($arr['pid'])){
            return 0;
        }
        return $arr['pid'];
    }

    /**
     * 判断玩家当前是否到了最后一次兑换
     * @param int $pid
     * @param array $info
     * @return bool
     */
    public function checkIfLast($pid, $info, $version = '1.7.3') {
        if(empty($info['stage'])){
            return false;
        }
        $shopArr = $this->getShopDiamondByPid($pid, $version);
        if($info['stage'] < count($shopArr) - 1){
            return false;
        }
        $shopInfo = $shopArr[$info['stage']];

        if($info['buyTimes'] >= $shopInfo['buyTimes']){
            return true;
        }
        return false;
    }

    /**
     * 判断当前玩家当前是否可用宝石兑换物品
     */
    public function canExchange($uid, $pid, $stage, $version = '1.7.3') {
        if(oo::compareVersion($version,'1.7.7')){
            $tmp = $this->getNewUserExchangeInfo($uid, $pid);
            if(isset($tmp[$stage])){
                $info = $tmp[$stage];
            }else{
                $info = [];
            }
        }else{
            $info = $this->getUserExchangeInfo($uid, $pid);
            if(empty($info)){
                $info = ['stage' => 0, 'buyTimes' => 0];
            }
        }
        $shopInfoArr = $this->getShopDiamondByPid($pid, $version);
        if(!isset($shopInfoArr[$stage])){
            return false;
        }
        $shopInfo = $shopInfoArr[$stage];
        $curShopInfo = [];
        if(!oo::compareVersion($version,'1.7.7')){
            $curShopInfo = $shopInfoArr[$info['stage']];
        }
        if(empty($stage)){ //0阶
            //已过cd时间
            if(!empty($info['expire']) && $info['expire'] < time()){
                return true;
            }

            if(!oo::compareVersion($version,'1.7.7')){
                //还未到最后一阶
                if($info['stage'] && $info['stage'] < $shopInfo['stages'] - 1){
                    return false;
                }
                //最后一阶次数未完
                if($info['stage'] >= $shopInfo['stages'] - 1 && $info['buyTimes'] < $curShopInfo['times']){
                    return false;
                }
                //cd中
                if($info['stage'] && !empty($info['expire']) && $info['expire'] > time()){
                    return false;
                }
                //当前阶次数买完了
                if(empty($info['stage']) && $info['buyTimes'] >= $curShopInfo['times']){
                    return false;
                }
            }
            if(isset($info['buyTimes']) && $info['buyTimes'] >= $shopInfo['times']){
                return false;
            }
        }else{
            //已过cd时间
            if(!empty($info['expire']) && $info['expire'] < time()){
                return true;
            }
            if(!oo::compareVersion($version,'1.7.7')){
                if($info['stage'] > $stage){ //请求阶错误
                    return false;
                }
                if($info['stage'] + 1 < $stage){ //跨阶了
                    return false;
                }
                //当前阶次数未买完
                if($info['stage'] + 1 == $stage && $info['buyTimes'] < $curShopInfo['times']){
                    return false;
                }
                //当前阶已买完
                if($info['stage'] == $stage && $info['buyTimes'] >= $curShopInfo['times']){
                    return false;
                }
            }
            if(isset($info['buyTimes']) && $info['buyTimes'] >= $shopInfo['times']){
                return false;
            }
        }

        $assetsInfo = oo::commonOprModel('member')->getUserAssetsInfo($uid);
        //钻石不足
        if($shopInfo['price'] > (int)$assetsInfo['diamond']){
            return false;
        }
        return true;
    }

    /**
     * 使用钻石兑换物品
     * @param int $uid
     * @param int $pid
     */
    public function diamondExchange($uid, $pid, $stage, $version = '1.7.3') {
        $shopInfoArr = $this->getShopDiamondByPid($pid, $version);
        if(!isset($shopInfoArr[$stage])){
            return false;
        }
        if(oo::compareVersion($version, '1.7.7')){
            $info = $this->getNewUserExchangeInfo($uid, $pid);
        }else{
            $info = $this->getUserExchangeInfo($uid, $pid);
        }
        $shopInfo = $shopInfoArr[$stage];

        //扣除钻石
        $ret = oo::commonOprModel('member')->optProperty(
            $uid,['diamond' => $shopInfo['price']],'-',12,'钻石兑换,消耗钻石:'.$pid.':'.$stage
        );

        if(!$ret){
            oo::logs()->debug(['uid'=> $uid,'data'=>$shopInfo['price']],'getDiamond.log', date('Ymd').'/');
            return false;
        }

        if(oo::compareVersion($version,'1.7.7')){
            $upArr = $info;
            if(!isset($upArr[$stage])){
                $upArr[$stage] = ['buyTimes' => 1];
            }else{
                $upArr[$stage]['buyTimes'] += 1;
            }
        }else{
            $upArr = ['stage' => (int)$stage];
            if($stage != $info['stage']){ //跨阶或重新开始买
                $upArr['buyTimes'] = 1;//重置次数
            }else{
                $times = $info['buyTimes']+1 >= $shopInfo['times'] ? $shopInfo['times'] : $info['buyTimes']+1;
                $upArr['buyTimes'] = (int)$times;
            }
        }
        //最后一阶了,更新倒计时,世界时间第二天0点
        $expire = $this->getExpire();
        if(oo::compareVersion($version,'1.7.7')){
            $upArr[$stage]['expire'] = (isset($upArr[$stage]['expire']) && $upArr[$stage]['expire'] > time()) ? $upArr[$stage]['expire'] : $expire;
        }else{
            $upArr['expire'] = $expire;
        }
        //更新兑换信息
        $ret = oo::commonOprRedis("user")->hSet(okeys::userDdiamond($uid), $pid, json_encode($upArr));
        if(!$ret){
            $log = json_encode(['act' => 'up user diamond exchange stage fail','value' => $stage+1]);
            oo::logs()->debug(['uid'=> $uid, 'data'=>$log],'getDiamond.log', date('Ymd').'/');
            return false;
        }

        $reward = $this->getReward($uid, $shopInfo['gbaseReward']);
        if(isset($shopInfo['gbaseReward']['crazyPassExp'])){
            $ret = oo::commonOprModel('member')->sendReward($uid, 38, $shopInfo['gbaseReward']['crazyPassExp'],13,'钻石兑换,增加物品:'.$pid.':'.$stage);
        }else{
            $ret = oo::commonOprModel('member')->optProperty($uid,$reward,'+',13,'钻石兑换,增加物品:'.$pid.':'.$stage);
        }
        
        if(!$ret){
            $log = json_encode(['act'=>'diamond exchange attr fail,stage:'.((int)$stage+1),'value'=>$shopInfo['gbaseReward']]);
            oo::logs()->debug(['uid'=> $uid,'data'=>$log],'getDiamond.log', date('Ymd').'/');
        }
        return $ret;
    }

    public function getReward($uid, $gbaseReward) {
        if(is_array($gbaseReward) && isset($gbaseReward['coins'])){
            $gbaseReward['money'] = oo::commonOprModel('goods')->getGoodCoins($uid, $gbaseReward['coins']);
            $num = isset($gbaseReward['num']) ? (int)$gbaseReward['num'] : 1;
            if($num < 0){
                $num = 1;
            }
            $gbaseReward['money'] = $gbaseReward['money'] * $num;
            unset($gbaseReward['coins'], $gbaseReward['num']);
        }
        return $gbaseReward;
    }

    /**
     * 金币/体力不足直接钻石兑换列表
     * @param $gid int
     * @return array
     */
    public function getNotEnoughDiamond($uid, $gid = 0) {
        $arr = oo::commonOprRedis("common")->hGetAll(okeys::notEnouthDiamond());
        ksort($arr);
        if(empty($arr)){
            $tb = otable::diamondCrazy();
            $pids = self::COINNOTENOUGH . ',' . self::SPINNOTENOUGH;
            $sql = "SELECT * FROM {$tb} WHERE pid IN({$pids})";
            $rs = oo::commonOprDb('common')->getAll($sql,1);
            $arr = [];
            foreach($rs as $k => $v){
                $v['gbaseReward'] = json_decode($v['gbaseReward'], true);
                $arr[$v['gid']] = $v;
            }
            unset($v['gExpire'], $v['times']);
            //存redis
            foreach($arr as $k => $v){
                $arr[$k] = $v;
                oo::commonOprRedis("common")->hSet(okeys::notEnouthDiamond(), $k, json_encode($v));
            }
        }
        foreach($arr as $k => $v){
            $v = is_array($v) ? $v : (array)json_decode($v, true);
            if(!is_array($v) || empty($v)){
                continue;
            }
            unset($v['gExpire'], $v['times']);
            if(isset($v['gbaseReward']['props'])){
                $v['propId'] = $v['gbaseReward']['props'];
                $v['num'] = 1;
            }else{
                $v['gbaseReward'] = $this->getReward($uid, $v['gbaseReward']);
            }
            $arr[$k] = is_array($v) ? $v : (array)json_decode($v, true);
        }

        if($gid){
            return !isset($arr[$gid]) ? [] : $arr[$gid];
        }

        return $arr;
    }

    /**
     * 返回给客户端的结构
     */
    public function notEnoughWithClient($uid) {
        $tmp = $this->getNotEnoughDiamond($uid);
        $data = [
            'diamondCoin' => [],
            'diamondSpin' => [],
        ];
        foreach($tmp as $v) {
            $v['id'] = $v['gid'];
            $v['addRatio'] = empty($v['gaddRatio']) ? '0' : $v['gaddRatio'];
            unset($v['gaddRatio']);
            if($v['pid'] == self::SPINNOTENOUGH){
                $v['num'] = $v['gbaseReward']['spins'];
                unset($v['gbaseReward']);
                $data['diamondSpin'][] = $v;
            }else{
                $v['num'] = $v['gbaseReward']['money'];
                unset($v['gbaseReward']);
                $data['diamondCoin'][] = $v;
            }
        }
        return $data;
    }
}
