<?php
/**
 * 任务相关
 */
class ModelTask{
    public $contypes = [];
    public $errCode = 0;
    protected $taskConfig = NULL;//任务配置
    public function __construct(){
        $this->dbToConfig();
    }

    /**
     * 获取用户当前缓存状态
     * @param int $uid
     * @param array $types
     * @return array
     */
    public function getCondition($uid, $types = array()) {
        if (!$uid || !$types || !is_array($types)) {
            return array();
        }
        $ret = array();
        foreach ($types as $type) {
            if (!in_array($type, $this->contypes)) {
                continue;
            }
            $key = okeys::task($uid, $type);
            $ret[$type] = (int)oo::commonOprRedis('usercache')->get($key);
        }
        return $ret;
    }

    /**
     * 获取已经奖励缓存
     * @param int $uid
     * @return array
     */
    public function getRewarded($uid) {
        $cacheKey = okeys::taskRewarded($uid);
        $ret = oo::commonOprRedis('usercache')->hGetAll($cacheKey);
        return ($ret && is_array($ret)) ? $ret : array();
    }

    /**
     * 领取奖励
     * @param int $uid
     * @param string $taskType  任务类型
     * @param bool $versionFalg  任务类型
     * @return mixed
     */
    public function reward($uid = 0, $taskType = '',$versionFalg = false){
        $data = ['code' => -1, 'msg' => '数据错误','data'=>[]];
        if (!$uid || !in_array($taskType, $this->contypes)) {
            return $data;
        }
        //判断是否已经领取了
        $alreadyRewarded = $this->getRewarded($uid);
        if($alreadyRewarded && $alreadyRewarded[$taskType]){
            return ['code' => -2, 'msg' => '已经领取了','data'=>[]];;
        }
        //获取次数 然后判断奖励
        $condition = $this->getCondition($uid, array($taskType));
        //任务配置
        $taskConfig = $this->taskConfig;
        //任务奖励
        $taskReward = [];
        //判断是否可以领取奖励
        foreach ($taskConfig as $k=>$v){
            if($v['task_type'] == $taskType){
                $taskReward = $v;
                if($condition[$taskType] < $v['target_times']){
                    $data = array('code' => -2, 'msg' => '未达到领取奖励次数','data'=>[]);
                    return $data;
                }
                break;
            }
        }

        //先发奖励  奖励类型  1：金币，2：体力，3：卡片，4：星星
        switch($taskReward['reward_type']){
            case 1:
                $reward_type = 'money';
                $coins =  oo::commonOprModel('goods')->getGoodCoins($uid,'coins01');
                $taskReward['reward_num'] = $taskReward['reward_num']*$coins;
                break;
            case 2:
                $reward_type = 'spins';
                break;
            case 3:
                //执行卡片逻辑
                $reward_type = 'card';
                $card = oo::commonOprModel('card')->getCardByType($uid,6,1);
                break;
            case 4:
                $reward_type = 'star';
                break;
            default:
                $data = array('code' => -3, 'msg' => '类型错误','data'=>[]);
                return $data;
                break;
        }

        if($reward_type){
            $bet   = 1;
            if($reward_type != 'card'){
                if(oo::commonOprModel('newvip')->checkVip($uid)){
                    $config = oo::commonOprModel('newvip')->getUserVipLv($uid, true,false,155);
                    $bet = max(intval($config['taskRewardBet']), 1);
                }
                $ret = oo::commonOprModel('member')->optProperty($uid,array($reward_type=>$taskReward['reward_num']*$bet),'+',60,'完成每日任务');
            }else{
                $ret = 1;
            }
            if($ret){
                // 先设置缓存
                $flg = $this->setRewarded($uid,$taskType);
                if ($flg) { // 设置领奖励缓存标识失败
                    //玩家资产信息
                    $memberAssets  = oo::commonOprModel('member')->getUserAssetsInfo($uid);
                    return [
                        'code'   =>1,
                        'msg'    =>'领取成功',
                        'data'   =>[
                            'type'   => $taskReward['reward_type'],
                            'addNum' => $taskReward['reward_num'] * $bet,
                            'info'   => $memberAssets,
                            'card'   => $card,
                            'newTask'=> self::refreshTaskList($uid,$taskType,$versionFalg),
                        ]
                    ];
                }
            }
        }
        return $data;
    }

    /**
     * 设置已领奖励缓存
     * @param int $uid
     * @param int $type
     * @return bool
     */
    public function setRewarded($uid, $type) {
        if (!$uid || !$type) {
            $this->errCode = -201;
            return false;
        }
        $cacheKey = okeys::taskRewarded($uid);
        $cache = oo::commonOprRedis('usercache')->hGetAll($cacheKey);
        !$cache && $cache = array();
        $cache[$type] = 1;
        $res = oo::commonOprRedis('usercache')->hMset($cacheKey,$cache);
        oo::commonOprRedis('usercache')->expire($cacheKey,oo::todayDeadline());
        return $res;
    }

    /**
     * 累加条件缓存
     * @param int $uid
     * @param string $type   slotSpins(-),slotMaxCoins（+）,Getshield（+）,slotSteal（+）
     * @param int $num
     * @return mixed
     */
    public function incCondition($uid, $type, $num = 1) {
        return true;
        if (!$uid || !in_array($type, $this->contypes)) {
            return false;
        }
        if(!in_array($type, array_column(self::getTaskList($uid),'taskType'))){
            return false;
        }
        $expire = strtotime("23:59:59") - time();
//        $ret = oo::commonOprCache('task')->increment(okeys::task($uid, $type), (int)$num, $expire);
        $ret = oo::commonOprRedis('usercache')->incrBy(okeys::task($uid, $type), (int)$num);
        oo::commonOprRedis('usercache')->expire(okeys::task($uid, $type), $expire);

        $getReward = self::getCondition($uid,$this->contypes);
        $list = $this->taskConfig;
        $getRewarded = self::getRewarded($uid);
        //重组数组
        foreach ($list as $k=>$v){
            if($v['task_type'] != $type){
                continue;
            }
            $fulfillNum = intval($getReward[$v['task_type']]);
            if($fulfillNum >= $v['target_times']){
                if($getRewarded[$v['task_type']]){
                    $flag = true;
                }else{
                    $flag = false;
                }
                $fulfillNum = $v['target_times'];
            }else{
                $flag = false;
            }
            $is_push = oo::commonOprRedis('usercache')->get(okeys::redPointLock($uid,"Task-{$type}"));
            if($fulfillNum == $v['target_times'] && $flag==false && !$is_push){
                oo::commonOprRedis('usercache')->setex(okeys::redPointLock($uid,"Task-{$type}"),1,oo::todayDeadline());
                oo::commonOprModel('Workerman')->push($uid,ocmd::$redPoint,['type'=>10]);
            }
        }
        return $ret;
    }

    /**
     *	数据库内容读入配置文件
     */
    public function dbToConfig(){
        $key = okeys::taskConfig();
        $cacheData = oo::commonOprRedis('common')->get($key);
        if ($cacheData) {
            $tempArr = json_decode($cacheData, 1);
            $this->taskConfig = $tempArr;
          	$this->contypes = array_column($tempArr,'task_type');
            return;
        }
        $table = otable::taskConfig();
        $sql = "SELECT * FROM $table where is_open = 1 ";
        $list = oo::commonOprDb('config')->getAll($sql, 1);
        $task_type = [];
        foreach ($list as $k=>$v){
            array_push($task_type,$v['task_type']);
        }
        $taskListJson = json_encode($list);
        oo::commonOprRedis('common')->set($key, $taskListJson);
        oo::commonOprRedis('common')->expireAt($key, oo::redisRandomExpire(strtotime("23:59:59")));//任务默认是一天
        $this->taskConfig = $list;
        $this->contypes = $task_type;
        return $list;
    }


    public function getTaskConfig($uid){
        if( empty($uid) && !$this->taskConfig ){
            return false;
        }
        $list = $this->taskConfig;
        if(count($list) < 1){
            return false;
        }
//        $curTaskList = ocache::t_userinfo($uid)->get(okeys::CurTaskList($uid));
        $curTaskList =oo::commonOprRedis('usercache')->hGetAll(okeys::CurTaskList($uid));
        if(empty($curTaskList)){
            $rand = array_rand($list,3);
            foreach ($list as $key=>$row){
                if(!in_array($key,$rand)){
                    unset($list[$key]);
                }
            }
            sort($list);
//            ocache::t_userinfo($uid)->set(okeys::CurTaskList($uid),array_column($list,'task_type'),oo::todayDeadline());
            oo::commonOprRedis('usercache')->hMset(okeys::CurTaskList($uid),array_column($list,'task_type'));
            oo::commonOprRedis('usercache')->expire(okeys::CurTaskList($uid),oo::todayDeadline());
        }else{
            foreach ($list as $key=>$row){
                if(!in_array($row['task_type'],$curTaskList)){
                    unset($list[$key]);
                }
            }
            sort($list);
        }
        return $list;
    }

    public function getList($uid){
        return $data = [
            'code' => 1,
            'msg'  => '请求成功',
            'data' => [
                'task'    =>self::getTaskList($uid),
                'achieve' =>oo::commonOprModel('achievement')->getAchieveList($uid),
                'progress'=>self::getTaskProgress($uid),
                'time'    =>strtotime("23:59:59") - time(),
                'invite'  =>[
                    'reward'=>['type'=>2, 'num' =>oo::commonOprModel('invite')->inviteConfig($uid)['base']],
                    'friendsList'  =>oo::commonOprModel('invite')->getInviteRewardList($uid)
                ],
                'taskFinishNum' => count(self::getRewarded($uid))
            ]
        ];
    }

    public function getTaskList($uid,$taskType = ''){
        $list = self::getTaskConfig($uid);
        if(!$list){
            return array('code' => -2,'msg'=>'数据错误', 'data' => []);
        }
        $lang = oo::getDefinedLang($uid);
        $taskArr = [];
        $getReward = self::getCondition($uid,$this->contypes); //查询奖励
        //查询用户领取领取状态
        $getRewarded = self::getRewarded($uid);
        //重组数组
        $coins =  oo::commonOprModel('goods')->getGoodCoins($uid,'coins01');
        foreach ($list as $k=>$v){
            $fulfillNum = intval($getReward[$v['task_type']]);
            if($fulfillNum >= $v['target_times']){
                //如果有领取记录 那就是领取了
                if($getRewarded[$v['task_type']]){
                    $flag = 2;
                }else{
                    $flag = 1;
                }
                $fulfillNum = $v['target_times'];
            }else{
                $flag = 0;
            }

            if($lang == 'zh'){
                $task_title = $v['task_title'];
            }else{
                $task_title = $v['task_title_'.$lang];
            }

            if($v['reward_type'] == 1){
                $num = $v['reward_num']*$coins;
            }else{
                $num = $v['reward_num'];
            }
            $taskArr[$k] = [
                'rewardType'=>$v['reward_type'],
                'num'=>$num,
                'desc'=>$task_title,
                'progress'=>$fulfillNum,
                'target'=>$v['target_times'],
                'status'=>$flag,
                'taskType'=>$v['task_type'],
            ];
            if($v['task_type'] == $taskType){
                return $taskArr[$k];
            }
        }
        return $taskArr;
    }

    /**
     * 任务进度
     * @param $uid
     * @return mixed
     * Created by: Owen
     * Created on: 2020/5/9 16:50
     */
  	public function getTaskProgress($uid){
        $ret = oo::commonOprModel('config')->getTaskProgressConfig();
        foreach ($ret as $key=>$row){
            $ret[$key]['status'] = intval(oo::commonOprRedis('common')->hGet(okeys::taskProgress(),okeys::taskProgress($uid,$row['progress'])));
        }
        return $ret;
    }

    /**
     * 任务进度奖励
     * @param $uid
     * @param $progress
     * @return array|bool
     * Created by: Owen
     * Created on: 2020/5/9 16:50
     */
    public function getTaskProgressReward($uid,$progress){
        if(oo::commonOprRedis('common')->hGet(okeys::taskProgress(),okeys::taskProgress($uid,$progress))){
            return false;
        }
        $list = $this->taskConfig;
        $getReward = $this->getCondition($uid,$this->contypes);
        $serverProgress = 0;
        foreach ($list as $k=>$v){
            $fulfillNum = intval($getReward[$v['task_type']]);
            if($fulfillNum >= $v['target_times']){
                $serverProgress++;
            }
        }
        if($serverProgress<$progress){
            return false;
        }
        $ret = oo::commonOprModel('config')->getTaskProgressConfig($progress);
        if(empty($ret)){
            return false;
        }
        oo::commonOprModel('member')->optProperty($uid,array('spins'=>intval($ret['spins'])),'+',61,'每日任务进度:'.$progress);
        oo::commonOprRedis('common')->hSet(okeys::taskProgress(),okeys::taskProgress($uid,$progress),1);
        return ['spins'=>$ret['spins']];
    }

    /**
     * 刷新当前任务
     * @param $uid
     * @param $taskType
     * @param $versionFlag
     * @return array
     * Created by: Owen
     * Created on: 2020/1/8 19:46
     */
    public function refreshTaskList($uid,$taskType,$versionFlag = false){
//        $curTaskList = ocache::t_userinfo($uid)->get(okeys::CurTaskList($uid));
        $curTaskList =oo::commonOprRedis('usercache')->hGetAll(okeys::CurTaskList($uid));
        if(empty($curTaskList)){
            return [];
        }
        $curTaskListNum = count($curTaskList);
        $list = array_column($this->taskConfig,'task_type');
        $list = array_diff($list,$curTaskList);
        $list = array_diff($list,array_keys(self::getRewarded($uid)));
        $key  = array_search($taskType,$curTaskList);
        unset($curTaskList[$key]);
        if($curTaskListNum == count($curTaskList)){
            return $versionFlag ? self::getTaskList2($uid,$taskType) :self::getTaskList($uid,$taskType);
        }
        $rand = array_rand($list,1);
        foreach ($list as $key=>$row){
            if($key==$rand){
                $curTaskList[$key] = $row;
                $taskType = $row;
                break;
            }
        }
        $newTaskList = [];
        foreach ($curTaskList as $row){
            $newTaskList[] = $row;
        }
//        ocache::t_userinfo($uid)->set(okeys::CurTaskList($uid),array_unique($newTaskList),oo::todayDeadline());
        oo::commonOprRedis('usercache')->hMset(okeys::CurTaskList($uid),array_unique($newTaskList));
        oo::commonOprRedis('usercache')->expire(okeys::CurTaskList($uid),oo::todayDeadline());
        return $versionFlag ? self::getTaskList2($uid,$taskType) :self::getTaskList($uid,$taskType);
    }


    /**
     *  1.5.0 新版配置 --------------------------------------------------------------------------------------------------
     */

    /**
     * id 与 task_type 映射
     * @param $id
     * @return mixed
     * Created by: Owen
     * Created on: 2020/5/9 17:42
     */
    public function taskMap($id){
        $task = array_column($this->taskConfig,null,'id');
        return $task[$id]['task_type'];
    }

    /**
     * 保护
     * @param $uid
     * @return string
     * Created by: Owen
     * Created on: 2020/5/9 16:57
     */
    public function getList2($uid){
        return oo::response(1,[
            'task'    =>self::getTaskList2($uid),
            'achieve' =>oo::commonOprModel('achievement')->getAchieveList2($uid),
            'progress'=>array_column(self::getTaskProgress($uid),'status'),
            'time'    =>strtotime("23:59:59") - time(),
            'taskFinishNum' => count(self::getRewarded($uid))
        ],'请求成功',true);
    }


    /**
     * 任务列表 -- 新版
     * @param $uid
     * @param string $taskType
     * @return array|mixed
     * Created by: Owen
     * Created on: 2020/5/9 16:50
     */
    public function getTaskList2($uid,$taskType = ''){
        $list = self::getTaskConfig($uid);
        if(!$list){
            return array('code' => -2,'msg'=>'数据错误', 'data' => []);
        }
        $taskArr = [];
        $getReward   = self::getCondition($uid,array_column($list,'task_type'));
        $getRewarded = self::getRewarded($uid);
        foreach ($list as $k=>$v){
            $fulfillNum = intval($getReward[$v['task_type']]);
            if($fulfillNum >= $v['target_times']){
                if($getRewarded[$v['task_type']]){
                    $flag = 2;
                }else{
                    $flag = 1;
                }
                $fulfillNum = $v['target_times'];
            }else{
                $flag = 0;
            }
            $taskArr[$k] = [
                'id'       =>$v['id'],
                'progress' =>$fulfillNum,
                'status'   =>$flag,
            ];
            if($v['task_type'] == $taskType){
                return $taskArr[$k];
            }
        }
        return $taskArr;
    }
}
