<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2020/2/3
 * Time: 21:17
 */

class ModelPet{
    public function getPetConfig($petId = 0,$versionFlag = false){
        $cacheKey = okeys::PetConfig("",$versionFlag);
        $arrJson = oo::commonOprRedis('config')->hGetAll($cacheKey);
        $arr = funs::getArrFromJsonArr($arrJson);
        if(empty($arr)||(!$petId&&empty($arr[$petId]))){
            $tb =  otable::PetConfig($versionFlag);
            $arr =  oo::commonOprDb('config')->getAll("SELECT * FROM {$tb}",MYSQLI_ASSOC);
            if(!empty($arr)){
                foreach ($arr as $k=>$v){
                    if($versionFlag){
                        $v['addExp']     = json_decode($v['addExp'],true)??[];
                        $v['skillBase']  = json_decode($v['skillBase'],true)??[];
                        $arr[$k] = $v;
                        $cache[$v['id']] = json_encode($v);
                    }else{
                        $cache[$v['id']] =  json_encode($arr[$k]);
                    }

                }
                $arr = array_column($arr,null,'id');
                oo::commonOprRedis('config')->hMset($cacheKey,$cache);
                oo::commonOprRedis('config')->expire($cacheKey,oo::redisRandomExpire(7*86400));
            }
        }
        $data = $petId===0?array_values($arr):$arr[$petId];
        return $data;
    }
    public function savePetConfig($data){
        $tb = otable::PetConfig(true);
        $petId  = $data['petId'];
        unset($data['petId']);
        $update = "";
        foreach ($data as  $key=>$row){
            $update .= "`$key`='$row',";
        }
        $update = trim($update,",");
        oo::commonOprDb('common')->query("UPDATE {$tb} SET {$update} WHERE id={$petId} LIMIT 1 ",false);
        oo::commonOprRedis('config')->delete(okeys::PetConfig("",true));
    }

    public function getPetExpConfig($lv = 0){
        $cacheKey = okeys::PetExpConfig();
        $arrJson = oo::commonOprRedis('config')->hGetAll($cacheKey);
        $arr = funs::getArrFromJsonArr($arrJson);
        if(empty($arr)||(!$lv&&empty($arr[$lv]))){
            $tb =  otable::PetExpConfig();
            $arr =  oo::commonOprDb('config')->getAll("SELECT * FROM {$tb} WHERE 1",MYSQLI_ASSOC);
            if(!empty($arr)){
                foreach ($arr as $k=>$v){
                    $cache[$v['lv']] =  json_encode($arr[$k]);
                }
                $arr = array_column($arr,null,'lv');
                oo::commonOprRedis('config')->hMset($cacheKey,$cache);
                oo::commonOprRedis('config')->expire($cacheKey,oo::redisRandomExpire(7*86400));
            }
        }
        $data = $lv===0?$arr:$arr[$lv]['exp'];
        return $data;
    }

    public function savePetExpConfig($data){
        $tb = otable::PetExpConfig();
        foreach ($data as  $key=>$row){
            oo::commonOprDb('common')->query("UPDATE {$tb} SET `exp`={$row} WHERE lv={$key} LIMIT 1 ",false);
        }
        oo::commonOprRedis('config')->delete(okeys::PetExpConfig());
    }

    /**
     * 获取宠物等级配置
     * @param $petId
     * @param $lv
     * @return array|mixed
     * Created by: Owen
     * Created on: 2020/8/25 15:47
     */
    public function getPetLevelConfig($petId=1,$lv=1){
        $cacheKey = okeys::PetLevelConfig($petId);
        $cache    = oo::commonOprRedis('Config')->hGet($cacheKey,$lv);
        if(empty($cache)){
            $tb    = otable::PetExpConfig2();
            $cache = oo::commonOprDb('config')->getOne("SELECT * FROM {$tb} WHERE petId={$petId} AND lv={$lv}",MYSQLI_ASSOC);
            if(!empty($cache)){
                oo::commonOprRedis('Config')->hSet($cacheKey,$lv,json_encode($cache));
            }
        }else{
            $cache = json_decode($cache,true);
        }
        return $cache;
    }

    /**
     * 孵化宠物
     * @param $uid
     * @param $petId
     * @return array
     * Created by: Owen
     * Created on: 2020/8/21 17:51
     */
    public function incubatePet($uid,$petId){
        $pet = self::getUserPet($uid,$petId);
        if(empty($pet)){
            $petConfig = self::getPetConfig($petId,true);
            if(empty($petConfig)){
                return ['code'=>-4,"msg"=>"宠物不存在"];
            }
            if($petConfig['incubateType'] == 0){
                $userAssetsInfo = oo::commonOprModel('member')->getUserAssetsInfo($uid);
                if($userAssetsInfo['levelId'] < $petConfig['incubateFrom']){
                    return ['code'=>-3,"msg"=>'等级不足解锁'];
                }
            }else if($petConfig['incubateType'] == 2){
                if(!oo::commonOprModel('card')->isGetAllCardByGroup($uid,$petConfig['incubateFrom'])){
                    return ['code'=>-3,"msg"=>'解锁条件不足'];
                }
            }
            $tb  = otable::UserPet($uid);
            $time = time();
            oo::commonOprDb('common')->query("INSERT INTO {$tb} (uid,petId,nick,getTime,star) VALUES ('{$uid}','{$petId}','pet','{$time}',-1)", false);
            $userPet = oo::commonOprDb('common')->getOne("SELECT * FROM {$tb} WHERE uid={$uid} AND petId={$petId} LIMIT 1", MYSQLI_ASSOC);
            oo::commonOprRedis('User')->hSet(okeys::UserPet2($uid),$petId,json_encode($userPet));
            oo::commonOprModel('ta')->setEventData($uid,"pet_unlock",["pet_unlock_id"=>$petId,]);
            return ['code'=>1,'data'=>self::getUserPet($uid,$petId)];
        }else{
            return ['code'=>-2,"msg"=>"宠物已激活"];
        }
    }

    /**
     * 激活宠物
     * @param $uid
     * @param $petId
     * @return string
     * Created by: Owen
     * Created on: 2020/8/21 17:50
     */
    public function activatePet($uid,$petId){
        $petList = self::getUserPet($uid,0,true);
        foreach ($petList as $row){
            if($row['petId'] == $petId && $row['selected'] == 0){
                self::updateUserPetInfo($uid,$row['petId'],['selected'=>1]);
            }else if($row['petId'] != $petId && $row['selected'] == 1){
                self::updateUserPetInfo($uid,$row['petId'],['selected'=>0]);
            }
        }
        oo::commonOprRedis('usercache')->setex(okeys::CurUserPet($uid),$petId,oo::redisRandomExpire(7*24*60*60));
        return oo::response(1,self::getUserPet($uid,$petId),"",true);
    }

    /**
     * 获取宠物信息
     * @param $uid
     * @param int $petId
     * @param bool $orig
     * @return array|mixed
     * Created by: Owen
     * Created on: 2020/8/21 17:50
     */
    public function getUserPet($uid,$petId = 0,$orig = false){
        $cacheKey = okeys::UserPet2($uid);
        $userPetArr = oo::commonOprRedis('User')->hGetAll($cacheKey);
        if(empty($userPetArr)){
            $tb         = otable::UserPet($uid);
            $userPetArr = oo::commonOprDb('common')->getAll("SELECT * FROM {$tb} WHERE uid={$uid}", MYSQLI_ASSOC);
            if(!empty($userPetArr)){
                foreach ($userPetArr as $row){
                    oo::commonOprRedis('User')->hSet($cacheKey,$row['petId'],json_encode($row));
                    $row['star'] == -1 && self::checkUserPetStar($uid,$row['petId'],$row['lv']);
                }
                oo::commonOprRedis('User')->expire($cacheKey,oo::redisRandomExpire(7*24*60*60));
            }
        }else{
            $userPetArr = array_values($userPetArr);
            foreach ($userPetArr as $key=>$row){
                $userPetArr[$key] = json_decode($row,true);
            }
        }
        foreach ($userPetArr as $key=>$row){
            !$orig && $userPetArr[$key] = array_merge($userPetArr[$key],self::getPetDetail($row['petId']??1,$row['lv']??1));
            if($row['selected'] == 1){
                oo::commonOprRedis('usercache')->setex(okeys::CurUserPet($uid),$row['petId'],oo::redisRandomExpire(7*24*60*60));
            }
            if($petId&&$petId==$row['petId']){
                $petId2 = $userPetArr[$key];
            }
        }
        if($petId2){
            $userPetArr = $petId2;
        }else if($petId){
            $userPetArr = [];
        }
        return $userPetArr;
    }

    /**
     * 更新用户宠物信息
     * @param $uid
     * @param $petId
     * @param $updateInfo
     * @return bool
     * Created by: Owen
     * Created on: 2020/8/24 19:50
     */
    public function updateUserPetInfo($uid,$petId,$updateInfo){
        if(empty($updateInfo)){
            return false;
        }
        $userPet = self::getUserPet($uid,$petId,true);
        if(empty($userPet)){
            return false;
        }
        foreach ($updateInfo as $key=>$row){
            $userPet[$key] = $row;
        }
        return self::setUserPetInfo($uid,$petId,$userPet);
    }

    /**
     * 原子加用户宠物数据
     * @param $uid
     * @param $petId
     * @param $updateInfo
     * @return bool
     * Created by: Owen
     * Created on: 2020/8/24 19:50
     */
    public function addUserPetInfo($uid,$petId,$updateInfo){
        if(empty($updateInfo)){
            return false;
        }
        $userPet = self::getUserPet($uid,$petId,true);
        if(empty($userPet)){
            return false;
        }
        foreach ($updateInfo as $key=>$row){
            $userPet[$key] += $row;
        }
        return self::setUserPetInfo($uid,$petId,$userPet);
    }

    /**
     * 更新入队
     * @param $uid
     * @param $petId
     * @param $info
     * @return bool
     * Created by: Owen
     * Created on: 2020/8/24 19:58
     */
    public function setUserPetInfo($uid,$petId,$info){
        $cacheKey = okeys::UserPet2($uid);
        $info['isLanding'] = 1;
        $bool = oo::commonOprRedis('User')->hSet($cacheKey,$petId,json_encode($info));
        oo::commonOprRedis('common')->expire($cacheKey,oo::redisRandomExpire(7*24*60*60));
        /** 数据落地标识 */
        oo::commonOprRedis('common')->zAdd(okeys::Landing("PET", $uid),time(),$uid);
        return $bool;
    }

    /**
     * 获取宠物经验增益详情数据
     * @param $petId
     * @param $lv
     * @return mixed
     * Created by: Owen
     * Created on: 2020/8/24 18:30
     */
    public function getPetDetail($petId,$lv){
        $lv     = max($lv,1);
        $config = self::getPetLevelConfig($petId,$lv);
        $userPet['nextLvExp']   = intval($config['exp']);
        $userPet['gainNum']     = self::getPetGain($petId,$lv);
        $userPet['nextGainNum'] = self::getPetGain($petId,$lv + 1);
        $userPet['nextStar']    = $config['star'];
        return $userPet;
    }

    /**
     * 当前激活宠物
     * @param $uid
     * @return false|int
     * Created by: Owen
     * Created on: 2020/8/21 17:50
     */
    public function getCurUserPet($uid){
        $cache = oo::commonOprRedis('usercache')->get(okeys::CurUserPet($uid));
        if($cache){
            return $cache;
        }
        return 1;
    }

    /**
     * 追加宠物经验
     * @param $uid
     * @param $petId
     * @param $exp
     * Created by: Owen
     * Created on: 2020/8/21 17:49
     */
    public function addUserPetExp($uid,$petId,$exp,$from = 0){
        self::addUserPetInfo($uid,$petId,['exp'=>$exp]) && self::upLevelUserPet($uid,$petId,$exp,$from);
    }

    /**
     * 宠物升级
     * @param $uid
     * @param $petId
     * @return bool
     * Created by: Owen
     * Created on: 2020/8/24 20:00
     */
    public function upLevelUserPet($uid,$petId,$exp = 0,$from = 0){
        $userPet = self::getUserPet($uid,$petId);
        if($userPet['nextLvExp']<=$userPet['exp'] && $userPet['nextLvExp'] != -1 && !empty($userPet['nextLvExp'])){
            $needAddStar= 0;
            $updateInfo = ['exp'=> - $userPet['nextLvExp'],'lv'=>1];
            $updateInfo['star'] = 0;
            $userPet['star'] == -1 && self::checkUserPetStar($uid,$petId,$userPet['lv']); // 检测宠物星星补发
            $config               = self::getPetLevelConfig($petId,$userPet['lv']);
            $needAddStar         += intval($config['star']);
            $updateInfo['star']  += intval($config['star']);
            $bool = self::addUserPetInfo($uid,$petId,$updateInfo);
            $bool && $needAddStar && oo::commonOprModel('member')->optProperty($uid,['star'=>$needAddStar],'+',112,"宠物升级：".$userPet['lv']) && self::upLevelUserPet($uid,$petId,$exp,$from);
            oo::commonOprModel('ta')->setEventData($uid,"pet_up",[
                "pet_up_id"=>$petId,
                "pet_up_addexptype"=>$from,
                "pet_up_addexp"=>$exp,
                "pet_up_oldlevel"=>$userPet['lv'],
                "pet_up_newlevel"=>$userPet['lv'] + 1,
            ]);
            $key = [1=>'pet_steal_level',3=>'pet_attack_level',2=>'pet_shield_level'][$petId];
            oo::commonOprModel('ta')->setEventData($uid,'user_set',[$key=>$userPet['lv'] + 1]);
            return $bool;
        }
        return false;
    }

    /**
     * 检测宠物星星
     * @param $uid
     * @param $petId
     * @param $lv
     * Created by: Owen
     * Created on: 2020/8/25 18:49
     */
    public function checkUserPetStar($uid,$petId,$lv){
        if($lv == 1){
            self::addUserPetInfo($uid,$petId,['star'=>0]);
        }else{
            $needAddStar = 0;
            $levelId     = [];
            for($i=1;$i<$lv;$i++){
                $config       = self::getPetLevelConfig($petId,$i);
                $needAddStar += intval($config['star']);
                $levelId[] = $i;
            }
            self::addUserPetInfo($uid,$petId,['star'=>$needAddStar + 1]) && oo::commonOprModel('member')->optProperty($uid,['star'=>$needAddStar],'+',112,"宠物等级星星补发：".implode(',',$levelId));
        }
    }

    /**
     * 喂食宠物（免费粮食）
     * @param $uid
     * @param $petId
     * @param $refreshTime
     * @return string
     * Created by: Owen
     * Created on: 2020/8/21 17:49
     */
    public function freeFeedPet($uid,$petId,$refreshTime = 0){
        $cacheKey = okeys::FreeFeedPet($uid);
        if($refreshTime){
            $time = time();
            $data['freeFeedStatus'] = $time + 24*60*60;
            oo::commonOprRedis('common')->setex($cacheKey,1,24*60*60);
            return oo::response(1,$data,"刷新成功");
        }
        if(oo::commonOprRedis('common')->get($cacheKey)){
             return oo::response(-2,[],"已喂食");
        }
        $time = time();
        $userPet = self::getUserPet($uid,$petId);
        if(empty($userPet)){
            return oo::response(-3,[],"宠物未激活");
        }
        if($userPet['feedEffecteTime']<$time){
            $feedEffecteTime = $time + 15*60;
        }else{
            $feedEffecteTime = $userPet['feedEffecteTime'] + 15*60;
        }
        $userPet['lastFeedTime']    = $time;
        $userPet['feedEffecteTime'] = $feedEffecteTime;
        self::updateUserPetInfo($uid,$petId,['lastFeedTime'=>$time,'feedEffecteTime'=>$feedEffecteTime]);
        oo::commonOprRedis('common')->setex($cacheKey,1,24*60*60);

        //免费喂食标记
        oo::commonOprRedis('statistics')->setex(okeys::participationPetKey($uid, $petId), 0, oo::todayDeadline());

        $data['petData']        = $userPet;
        $data['freeFeedStatus'] = $time + 24*60*60;

        oo::commonOprModel('ta')->setEventData($uid,"pet_feed",[
            "pet_feed_id"=>$petId,
            "pet_feed_type"=>1,
            "pet_feed_remain_time"=>max($feedEffecteTime - time(),0),
        ]);
        return oo::response(1,$data,"喂食成功",true);
    }

    /**
     * 喂食宠物
     * @param $uid
     * @param $petId
     * @param $addTime
     * @return bool
     * Created by: Owen
     * Created on: 2020/8/24 20:03
     */
    public function feedPet($uid,$petId,$addTime = 0,$from = 0){
        if($addTime){
            $activateTime = $addTime;
        }else{
            $petConfig = self::getPetConfig($petId,true);
            self::addUserPetExpBy($uid,$petId,"feedAddExp");
            $activateTime = $petConfig['activateTime'];
        }
        $time = time();
        $userPet = self::getUserPet($uid,$petId);
        if($userPet['feedEffecteTime']<$time){
            $feedEffecteTime = $time + $activateTime;
        }else{
            $feedEffecteTime = $userPet['feedEffecteTime'] + $activateTime;
        }
        //付费喂食标记
        oo::commonOprRedis('statistics')->setex(okeys::participationPetKey($uid, $petId), 1, oo::todayDeadline());
        oo::commonOprModel('ta')->setEventData($uid,"pet_feed",[
            "pet_feed_id"=>$petId,
            "pet_feed_type"=>$from,
            "pet_feed_remain_time"=>max($feedEffecteTime - time(),0),
        ]);
        return self::updateUserPetInfo($uid,$petId,['lastFeedTime'=>$time,'feedEffecteTime'=>$feedEffecteTime]);
    }

    /**
     * 使用宠物技能
     * @param $uid
     * @param $petId 1偷宠物 2盾牌宠物 3打宠物
     * @param int $num
     * @return bool|float|int|array
     * @throws Exception
     * Created by: Owen
     * Created on: 2020/8/21 17:49
     */
    public function usePetSkill($uid,$petId,$num = 0){
        if($petId != self::getCurUserPet($uid)){
            return false;
        }
        $userPet = self::getUserPet($uid,$petId);
        if(!empty($userPet) && $userPet['feedEffecteTime']>time()){
            $gainNum = self::getPetGain($petId, $userPet['lv']);
            if ($petId == 1) {
                $gainNum = $gainNum * 0.01;
                $num = abs(intval($num * $gainNum));
                return [$num,$gainNum];
            }else if ($petId == 2){
                if(IS_DEBUF){
                    return true;
                }
                if(oo::commonOprRedis('common')->setnx(okeys::PetSkillToday($uid),1)){
                    oo::commonOprRedis('common')->expire(okeys::PetSkillToday($uid),oo::todayDeadline());
                   return true;
                }
                if(random_int(0,100)<$gainNum){
                    return true;
                }
            }else if($petId == 3){
                return $num * $gainNum * 0.01;
            }
        }
        return false;
    }

    /**
     * 获取宠物收益值
     * @param $petId
     * @param $lv
     * @return float|int
     * Created by: Owen
     * Created on: 2020/8/21 17:48
     */
    public function getPetGain($petId,$lv){
        $config = self::getPetLevelConfig($petId,$lv);
        return intval($config['skill']);
    }

    /**
     * 追加宠物经验
     * @param $uid
     * @param $petId
     * @param $from
     * @return bool
     * Created by: Owen
     * Created on: 2020/9/17 19:15
     */
    public function addUserPetExpBy($uid,$petId,$from,$bet=1,$rid=122,$reason=''){
        if($from != "feedAddExp" && self::getCurUserPet($uid) != $petId){
            return false;
        }
        $config    = self::getPetConfig($petId,true);
        $expConfig = $config['addExp'];
        $userPetLv = self::getUserPet($uid,$petId)['lv'];
        $expReward = [];
        foreach ($expConfig as $exp){
            if($userPetLv <= $exp['minLv']){
                $expReward = $exp;
                break;
            }
        }
        if(empty($expReward[$from])){
            return false;
        }
        $count = intval($expReward[$from]*$bet);
        self::addUserPetExp($uid,$petId,$count,intval(["feedAddExp"=>1,"attackAddExp"=>2,"defenseAddExp"=>2,"stealAddExp"=>2][$from]));
        oo::commonOprModel('currency')->log($uid,8,"+",$count,0,$rid,$reason."基数{$expReward[$from]},bet:{$bet}");
        return $expReward[$from];
    }
}
