<?php
defined('IN_WEB') or die( 'Include Error!');
/**
 * 用户道具
 */
class ModelProps {
	private $_propsIdList = [];
    public function __construct(){

    }

    public function getPropsConfig(){
        if(empty($this->_propsIdList)){
            $this->_propsIdList = oo::cfg('props');
        }
        return $this->_propsIdList;
    }


    /**
	 * 获取用户的道具
	 * @param  uid       用户uid
	 * @param  id        道具ID
	 * @return mixed 返回用户道具数组，引用方式
	 */
    public function getUserProps($uid, $id = 0) {
        $propsConfig = $this->getPropsConfig();
        $outs = [];
        if($id != 0){
            if (!$uid || !in_array($id,array_keys($propsConfig))){
                return [];
            }
            $propsInfo = self::getUserPropsData($uid, $id);
            if(!empty($propsInfo) && $propsInfo['count'] > 0){
                $propsInfo['props'] = $propsConfig[$id];
                $out = $this->checkStatus($uid,$propsInfo);
                $outs = [
                    "id"=>$out['id'],
                    "count"=>$out['count'],
                    "props"=>$propsInfo['props'],
                    "value"=>null,
                ];
            }
        }else{
            $propsInfo = self::getUserPropsData($uid);
            if(!empty($propsInfo)){
                foreach ($propsInfo as $key=>$row){
                    if($row['count'] > 0){
                        $temp = $row;
                        $temp['props'] = $propsConfig[$row['id']];
                        $checkData = $this->checkStatus($uid,$temp);
                        if($checkData){
                            $outs[] = [
                                "id"=>$checkData['id'],
                                "count"=>$checkData['count'],
                                "props"=>$checkData['props'],
                                "value"=>null,
                            ];
                        }
                    }
                }
            }
        }
        return $outs;
    }

	public function getUserProps2($uid, $id = 0) {
        $propsConfig = $this->getPropsConfig();
        $out = [];
		if($id != 0){
            if (!$uid || !in_array($id,array_keys($propsConfig))){
                return [];
            }
            $propsInfo = self::getUserPropsData($uid, $id);
            if(!empty($propsInfo) && $propsInfo['count'] > 0){
                $propsInfo['props'] = $propsConfig[$id];
                $out = $this->checkStatus($uid,$propsInfo);
            }
        }else{
            $propsInfo = self::getUserPropsData($uid);
            if(!empty($propsInfo)){
                foreach ($propsInfo as $key=>$row){
                    if($row['count'] > 0){
                        $temp = $row;
                        $temp['props'] = $propsConfig[$row['id']];
                        $checkData = $this->checkStatus($uid,$temp);
                        if($checkData){
                            $out[] = $checkData;
                        }
                    }
                }
            }
        }
		return $out;
	}

    /**
     * 检测道具过期时间
     * @param $uid
     * @param $data
     * @return mixed
     * Created by: Owen
     * Created on: 2021/1/25 15:53
     */
	public function checkStatus($uid,$data){
        if($data['id'] == 37){
            $curTime = time();
            $spins = max(intval(oo::commonOprRedis("common")->ttl(okeys::PropsExpire($uid,"37-spins"))),0);
            $coins = max(intval(oo::commonOprRedis("common")->ttl(okeys::PropsExpire($uid,"37-coins"))),0);
            if($coins > 0 || $spins > 0){
                $data['value'] = [
                    'spins' => [
                        'time'       => $curTime + $spins,
                        'buyTimes'   => $spins == 0 ? 1 : 0,
                        'totalTimes' => 1,
                    ],
                    'coins' => [
                        'time'       => $curTime + $coins,
                        'buyTimes'   => $coins == 0 ? 1 : 0,
                        'totalTimes' => 1,
                    ],
                    'buyTime'=> intval(oo::commonOprRedis("common")->get(okeys::PropsExpire($uid,"37-buy")))
                ];
            }else{
                $this->decUserProps($uid,$data['id'],$data['count']);
                return [];
            }
        }
        return $data;
    }

    /**
     * 获取用户道具信息
     * @param $uid
     * @param int $id
     * @return array|mixed
     * Created by: Owen
     * Created on: 2020/5/7 18:33
     */
	public function getUserPropsData($uid,$id = 0){
	    $cacheKey = okeys::UserProps($uid);
	    if($id){
            $cache = oo::commonOprRedis('common')->hGet($cacheKey,$id);
            if(!empty($cache)){
                return json_decode($cache,true);
            }
            $tb  = otable::userprops($uid);
            $ret = oo::commonOprDb('common')->getOne("SELECT * FROM {$tb} WHERE uid = {$uid} AND id={$id} LIMIT 1", MYSQLI_ASSOC);
            $data = [];
            if(!empty($ret)){
                oo::commonOprRedis('common')->hSet($cacheKey,$id,json_encode($ret));
                $data = $ret;
            }
            oo::commonOprRedis('common')->expire($cacheKey,oo::redisRandomExpire(7*24*60*60));
            return $data;
        }else{
            $cache = oo::commonOprRedis('common')->hGetAll($cacheKey);
            if(!empty($cache)){
                $cacheTemp = [];
                foreach ($cache as $row){
                    $cacheTemp[] = json_decode($row,true);
                }
                return $cacheTemp;
            }
            $tb  = otable::userprops($uid);
            $ret = oo::commonOprDb('common')->getAll("SELECT * FROM {$tb} WHERE uid = {$uid}", MYSQLI_ASSOC);
            foreach ($ret as $row){
                oo::commonOprRedis('common')->hSet($cacheKey,$row['id'],json_encode($row));
            }
            oo::commonOprRedis('common')->expire($cacheKey,oo::redisRandomExpire(7*24*60*60));
            return $ret;
        }
    }

    /**
     * 保存数据
     * @param $uid
     * @param $id
     * @param $info
     * @return bool
     * Created by: Owen
     * Created on: 2020/5/7 20:03
     */
    public function updateUserPropsData($uid,$id,$info){
        $cacheKey = okeys::UserProps($uid);
        $info['isLanding'] = 1;
        $ret = oo::commonOprRedis('common')->hSet($cacheKey,$id,json_encode($info));
        oo::commonOprRedis('common')->expire($cacheKey,oo::redisRandomExpire(7*24*60*60));
        /** 数据落地标识 */
        oo::commonOprRedis('common')->zAdd(okeys::Landing("PROPS", $uid),time(),$uid);
        return $ret;
    }

    /**
     * 添加道具
     * @param $uid
     * @param $id
     * @param $count
     * @param int $type
     * @return array|bool
     * Created by: Owen
     * Created on: 2019/12/19 19:48
     */
	public function addUserProps($uid, $id, $count, $type = 0 ,$rid=2001,$ext='') {
        if($id == 22){ //钻石发放入口关闭
            return true;
        }
	    $propsConfig  =$this->getPropsConfig();
        if (!$uid || !in_array($id,array_keys($propsConfig))){
            return false;
        }
        $propsInfo = self::getUserPropsData($uid, $id);
        $propsData = $propsConfig[$id];
        if(empty($propsInfo)){
            $tb    = otable::userprops($uid);
            $now   = time();
            $query = "INSERT INTO {$tb} (uid,id,`type`,status,`count`,expire,`time`) VALUES ({$uid}, {$id}, {$type}, 0, {$count}, 0, {$now}) ON DUPLICATE KEY UPDATE `type`={$type},`status`=0,`count`={$count},`expire`=0,`time`={$now}";
            oo::commonOprDb('common')->query($query);
            $cacheKey = okeys::UserProps($uid);
            oo::commonOprRedis('common')->hSet($cacheKey,$id,json_encode([
                'uid'   =>$uid,
                'id'    =>$id,
                'type'  =>$type,
                'status'=>0,
                'count' =>$count,
                'expire'=>0,
                'time'  =>$now,
            ]));

            oo::commonOprModel('currency')->log($uid,"props","+",$count,$count,$rid,"{$ext}获得道具：".$propsData['msg']);
        }else{
            $propsInfo['count'] = $propsInfo['count'] + $count;
            self::updateUserPropsData($uid, $id,$propsInfo);
            oo::commonOprModel('currency')->log($uid,"props","+",$count,$propsInfo['count'],$rid,"{$ext}获得道具：".$propsData['msg']);
        }

        return ['code'=>1];
	}

    /**
     * 减少道具数量
     * @param $uid
     * @param $id
     * @param $count
     * @return bool|void
     * Created by: Owen
     * Created on: 2020/5/7 20:03
     */
    public function decUserProps($uid, $id, $count){
        $PropsConfig = $this->getPropsConfig();
        if (!$uid || !in_array($id,array_keys($PropsConfig))){
            return false;
        }
        $propsInfo = self::getUserPropsData($uid, $id);
        if(empty($propsInfo)){
            return false;
        }
        $propsInfo['count'] = max(0,$propsInfo['count'] - $count);

        $propsData = $PropsConfig[$id];
        oo::commonOprModel('currency')->log($uid,"props","-",$count,$propsInfo['count'],2002,"使用道具：".$propsData['msg']);

        return self::updateUserPropsData($uid, $id,$propsInfo);
    }

    /**
     * 使用用户的道具
     * @param $uid
     * @param int $id
     * @param int $useCount
     * @return mixed
     * Created by: Owen
     * Created on: 2019/12/19 19:55
     */
	public function useUserProps($uid, $id = 1, $useCount = 1 , $argc = []) {
	    $propsConfig=$this->getPropsConfig();
        if (!$uid || !in_array($id,array_keys($propsConfig))){
            return oo::response(-1);
        }
        $retProps = self::getUserProps($uid, $id);
        if(empty($retProps)){
            return oo::response(-2);
        }
        $propsData = $propsConfig[$id];
        $data = [];
        $myPropsNum = $retProps['count'];
        if($id == 8){
            $singleNum = $useCount;
            $useCount  = 1;
        }else{
            $singleNum = 1;
        }
        if(0 > $myPropsNum - $singleNum){
            return oo::response(-2);
        }

        self::decUserProps($uid,$id,$singleNum * $useCount);
        $version      = oo::commonOprModel('user')->getUserVersion($uid);
        $versionFlag = oo::compareVersion($version,'1.7.3');
        $activityLock = oo::commonOprModel('activitynew')->activityLock($uid,'card');
        for ($i=0;$i<$useCount;$i++){
            $myPropsNum = $myPropsNum - $singleNum;
            if($myPropsNum < 0){
                break;
            }
            if (in_array($propsData['id'],[1,2,3,4])){
                $data   = oo::commonOprModel('card')->getCardByType($uid,$propsData['id'],0);
                oo::commonOprModel('ta')->setEventData($uid,"chest",["chest_id"=>$propsData['id'],"chest_source"=>0,"chest_activity_ratio"=>$activityLock?0.5:0,"chest_reward_card_list"=>array_column($data['card'],"id")]);
                break;
            }else if($propsData['id'] == 7){
                $temp = [];
                if($versionFlag){
                    $data[$i]['index'] = oo::commonOprModel('luckydraw')->action($uid,$temp);
                    $data[$i]['data'] = $temp;
                }else{
                    $data['rewardIndex'][] = oo::commonOprModel('luckydraw')->action($uid,$temp);
                }
            }else if($propsData['id'] == 8){
                oo::commonOprModel('pet')->addUserPetExp($uid,$argc['petId'],$singleNum,3);
                $data['petData']  = oo::commonOprModel('pet')->getUserPet($uid,$argc['petId']);
                $userAssetsInfo   = oo::commonOprModel('member')->getUserAssetsInfo($uid);
                $data['userData']['star'] = $userAssetsInfo['star'];
            }else if($propsData['id'] == 9){
                oo::commonOprModel('pet')->feedPet($uid,$argc['petId'],0,3);
                $data = oo::commonOprModel('pet')->getUserPet($uid,$argc['petId']);
            }else if(in_array($propsData['id'],[19,20,21,29,30])){
                $data = self::rewardChest($uid,$propsData['id'],"背包道具",2002,1);
            }
        }
        return oo::response(1,$data,'',true);
	}

    /**
     * 获取宝箱奖励
     * @param $uid
     * @param $propsId
     * @param $reason
     * @return bool
     * Created by: Owen
     * Created on: 2020/9/14 17:30
     */
	public function rewardChest($uid,$propsId,$reason = "",$rid=2002,$skin = 0){
        $config = self::getChestData($uid,$propsId,true,$skin);
        if(!$config){
           return false;
        }
        $userCardInfo = oo::commonOprModel('card')->getUserCardInfo($uid);
        $userJokerNum = $userCardInfo['jockerNum'];
        $data['joker']  = 0;

        $version = oo::commonOprModel('user')->getUserVersion($uid);
        //1.8.5特殊宝箱添加小丑卡保底值,保底值+配置值>=10000则必出小丑卡
        $minGuaranteeNum = empty($userCardInfo['minGuaranteeNum']) ? 0 : (int)$userCardInfo['minGuaranteeNum'];
        if(!empty($userCardInfo['jockerNum'])){
            $minGuaranteeNum += 250*(int)$userCardInfo['jockerNum'];
        }
        $calConfNum = $config['jokerCardNum'] <= 0 ? 0 : ceil(10000 / $config['jokerCardNum']);
        $anchorNum = $minGuaranteeNum + $calConfNum;
        $data['joker']  = 0;
        $cardUpdateInfo = [];
        if(!oo::commonOprRedis('User')->get(okeys::JokerCard($uid))){
            if($config['jokerCardNum'] != 0 && (rand(0,$config['jokerCardNum']) < 1 || $anchorNum >= 10000)) {
                $config['cardNum'] = $config['cardNum'] -1;
                $cardUpdateInfo['minGuaranteeNum'] = 0; //开出小丑卡,保底值清零
                $data['joker'] = oo::commonOprModel('card')->setJokerCard($uid);
                oo::commonOprModel('statistics')->jokerCardSta($propsId,1,$uid,'宝箱开出',$rid);//小丑卡统计
            }else{
                //保底值增加
                $cardUpdateInfo['minGuaranteeNum'] = $anchorNum;
            }
            $cardUpdateInfo['jockerNum'] = 0;
        }

        if(!empty($cardUpdateInfo)){
            oo::commonOprModel('card')->updateUserCardInfo($uid,$cardUpdateInfo);
        }
        $cardData = oo::commonOprModel('card')->getCardByType($uid,$propsId,$config['cardNum'],[],$skin);
        $data['card']   = $cardData['card'];
        $spins   = $config['spinsNum'][oo::commonOprModel('slot')->get_rand(array_column($config['spinsNum'],"v"))]['num'];
        $coins   = $config['coinsNum'][oo::commonOprModel('slot')->get_rand(array_column($config['coinsNum'],"v"))]['num'];
        oo::commonOprModel('member')->optProperty($uid,['spins'=>$spins,'money'=>$coins],"+",$rid,"特殊宝箱:".$reason);
        $petExp  = $config['petExp'][oo::commonOprModel('slot')->get_rand(array_column($config['petExp'],"v"))]['num'];
        oo::commonOprModel('props')->addUserProps($uid, 8, $petExp,0,$rid);
        $food    = $config['petFood'];
        $food > 0 && oo::commonOprModel('props')->addUserProps($uid, 9, $food,0,$rid);

        $coins   && $data['props'][] = ['propsId'=>14,'num'=>$coins,'value'=>$coins];
        $spins   && $data['props'][] = ['propsId'=>15,'num'=>$spins,'value'=>$spins];
        $petExp  && $data['props'][] = ['propsId'=>8 ,'num'=>$petExp,'value'=>$petExp];
        $food    && $data['props'][] = ['propsId'=>9 ,'num'=>$food, 'value'=>$food];
        $data['propsId'] = $propsId;
        $data['skin']    = $skin ? $skin : [19 =>1,20 =>2,21=>3,29=>4,30=>5][$propsId];

        oo::commonOprModel('ta')->setEventData($uid,"chest_sp",[
            "chest_id"=>$skin,
            "chest_source"=>$rid,
            "chest_activity_ratio"=>oo::commonOprModel('activitynew')->activityLock($uid,'card') ? 0.5 : 0,
            "chest_reward_spin"=>intval($spins),
            "chest_reward_coin"=>intval($coins),
            "chest_reward_petfood"=>intval($food),
            "chest_reward_petexp"=>intval($petExp),
            "chest_reward_card_list"=>array_column($data['card'],'id') ,
            "chest_reward_card_joker"=>$data['joker'] > 0 ? 1 : 0
        ]);
        return $data;
    }

    /**
     * 宝箱数据
     * @param $id
     * @param $reward
     * @return mixed
     * Created by: Owen
     * Created on: 2020/9/14 15:20
     */
	public function getChestData($uid,$id,$reward = false,$skin = 0){
	    if(in_array($id,[19,20,21,29,30])){
            $userAssetsInfo = oo::commonOprModel('member')->getUserAssetsInfo($uid);
	        $conf = $skin ? oo::commonOprModel('config')->getChestSkinConfig($skin) : oo::commonOprModel('config')->getChestConfig($id);
            $conf = array_column($conf,NULL,'propsId');
            $cardNum      = $conf[17]['num'];
            $jokerCardNum = $conf[18]['num'];
            $coinsNumPro  = $this->getChestWeightByLevelId($conf[14]['pro'],$userAssetsInfo['levelId']);
            $spinsNumPro  = $this->getChestWeightByLevelId($conf[15]['pro'],$userAssetsInfo['levelId']);
            $petExpPro    = $this->getChestWeightByLevelId($conf[8]['pro'],$userAssetsInfo['levelId']);
            $food         = intval($conf[9]['num']);
            if($reward){
                return [
                    'cardNum'      => $cardNum,
                    'jokerCardNum' => $jokerCardNum,
                    'coinsNum'     => $coinsNumPro,
                    'spinsNum'     => $spinsNumPro,
                    'petExp'       => $petExpPro,
                    'petFood'      => $food,
                ];
            }else{
                $coinsNum = $coinsNumPro ? array_column($coinsNumPro,'num') : [];
                $spinsNum = $spinsNumPro ? array_column($spinsNumPro,'num') : [];
                $petExp   = $petExpPro ? array_column($petExpPro  ,'num') : [];
                return [
                    'skin'         => $skin ? $skin : [19 =>1,20 =>2,21=>3,29=>4,30=>5][$id],
                    'cardNum'      => $cardNum,
                    'jokerCardNum' => $jokerCardNum,
                    'coinsNum'     => !empty($coinsNum) ? [min($coinsNum),max($coinsNum)] : [],
                    'spinsNum'     => !empty($spinsNum) ? [min($spinsNum),max($spinsNum)] : [],
                    'petExp'       => !empty($petExp)   ? [min($petExp),max($petExp)]     : [],
                    'petFood'      => $food,
                ];
            }

        }
	    return false;
    }

    /**
     * 根据等级获取配置
     * @param $data
     * @param $lv
     * @return array|mixed
     * Created by: Owen
     * Created on: 2021/3/3 12:11
     */
    public function getChestWeightByLevelId($data,$lv){
        $lv  = max($lv,1);
        $ret = [];
        foreach ($data as $d){
            if($d['lv'] <= $lv){
                $ret = $d['weight'];
            }else{
                break;
            }
        }
        return $ret;
    }

    public function setFirstPayPromotion($uid){
        oo::commonOprModel('props')->addUserProps($uid, 37, 1,0,304);
        $curTime  = time();
        $baseTime = 0;
        $config = oo::commonOprModel('activitynew')->activityLock($uid, 'shop_promotion', true);
        if(!empty($config)){
            $baseTime = max($config['activityData']['end'] - $curTime,0);
        }
        if(oo::commonOprRedis('common')->get(okeys::UserAbTest($uid)) > 1){
            $actionTime = $baseTime + 3 *24 *60 *60;
        }else{
            $actionTime = $baseTime + 7 *24 *60 *60;
        }
        oo::commonOprRedis("common")->setex(okeys::PropsExpire($uid,"37-spins"),1,$actionTime);
        oo::commonOprRedis("common")->setex(okeys::PropsExpire($uid,"37-coins"),1,$actionTime);
        oo::commonOprRedis("common")->setex(okeys::PropsExpire($uid,"37-buy"),$curTime,$actionTime);
        return [
            'spins' => [
                'time'       => $curTime + $actionTime,
                'buyTimes'   => 0,
                'totalTimes' => 1,
            ],
            'coins' => [
                'time'       => $curTime + $actionTime,
                'buyTimes'   => 0,
                'totalTimes' => 1,
            ],
            'buyTime' => $curTime
        ];
    }
}
