<?php
/**
 * 好友模块
 * @date 2022-3-28
 * @author JZW
 **/
namespace Game\Model\Friend;

use Framework\Lib\Utils;
use Framework\Logic\PacketCacheLogic;
use Framework\MVC\ModelManager;
use Framework\DB\Handler\CommonDBHandler;
use Framework\Logic\TemplateHelp;
use Framework\Model\CommonModel;
use Game\Constant\ClientErrorCode;
use Game\Constant\ConstTemplate\TemplateConst;
use Game\Constant\EventTypeDefine;
use Game\Constant\GameConstantDefine;
use Game\Constant\ModelTypeDefine;
use Game\Constant\TemplateDefine;
use Game\Data\Friends\FriendsData;
use Game\Logic\EventLogic;
use Game\Protobuf\FriendIntimacy;
use Game\Protobuf\GCUpdateFriendIntimacy;
use Game\Protobuf\PacketId;

class FriendModel
{
    use EventLogic;
    use PacketCacheLogic;

    use CommonDBHandler;
    use TemplateHelp;

    public int $playerId;
    private int $respondentPlayerId;

    private FriendsData $friends;


    public function setPlayerId($playerId)
    {
        $this->playerId = $playerId;
    }

    public function setRespondentPlayerId($respondentPlayerId)
    {
        $this->respondentPlayerId = $respondentPlayerId;
    }

    public function __construct()
    {
        $this->friends = new FriendsData();
    }

    //添加好友
    public function addFriend(): bool
    {
        //判断最大数量,不超过100
        $this->friends->respondentPlayerId = $this->playerId;
        $this->friends->playerId = $this->respondentPlayerId;
        if (!$this->friends->saveDB()){
            return false;
        }
        $this->friends->playerId = $this->playerId;
        $this->friends->respondentPlayerId = $this->respondentPlayerId;
        // 触发任务
        $param = array(
            GameConstantDefine::EVENT_KEY_NUM => 1,  //加好友数量
        );
        $this->triggerEvent(EventTypeDefine::EVENT_TYPE_TASK_ADD_FRIEND, $param);
        $this->triggerTargetEvent(EventTypeDefine::EVENT_TYPE_TASK_ADD_FRIEND, $param, $this->respondentPlayerId);
        return $this->friends->saveDB();
    }

    //查看我的好友列表
    //array [PlayerId=>好友数据Array,..]
    public function getMineList(): array
    {
        $this->friends->playerId = $this->playerId;
        if (!$this->friends->getList($result)){
            return [];
        }
        $ret = [];
        foreach ($result as $playerId => $infos){
            if ($playerId == $this->playerId){
                continue;
            }
            $info = json_decode($infos, true);
            $ret[$playerId] = $info;
        }
        return $ret;
    }

    //获取我的好友PlayerId列表
    public function getMinePlayerIdList(): array
    {
        $this->friends->playerId = $this->playerId;
        if (!$this->friends->getList($result)){
            return [];
        }
        $ret = [];
        foreach ($result as $playerId => $infos){
            if ($playerId == $this->playerId){
                continue;
            }
            $ret[$playerId] = json_decode($infos, true);
        }
        return $ret;
    }

    //查看好友数量(包含黑名单)
    public function getMineNumber(): int
    {
        $player = $this->getMinePlayerIdList();
        return count($player);
    }

    //删除我的好友
    public function delMineFriend(): bool
    {
        $this->friends->playerId = $this->playerId;
        $this->friends->respondentPlayerId = $this->respondentPlayerId;
        if (!$this->friends->deleteDB($ret)){
            return false;
        }
        $this->friends->playerId = $this->respondentPlayerId;
        $this->friends->respondentPlayerId = $this->playerId;
        return $this->friends->deleteDB($ret);
    }

    public function checkFriend(): bool
    {
        if ($this->playerId == $this->respondentPlayerId){
            return true;
        }
        $this->friends->playerId = $this->playerId;
        $this->friends->respondentPlayerId = $this->respondentPlayerId;
        $this->friends->getOneFriend($data);
        return (is_array($data) && count($data) > 0);
    }

    //精确搜索好友
    public function preciseSearch($key, array $blackList): array
    {
        $playerIds = [];
        /**
         * @var CommonModel $common
         */
        $common = ModelManager::getInstance()->getModel(ModelTypeDefine::COMMON);
        $ret1 = $common->search(CommonModel::TYPE_PLAY_NAME_PLAYER, $key);
        if ($ret1 != "" && $ret1 != $this->playerId) {
            $playerIds[] = $ret1;
        }

        $ret2 = $common->search(CommonModel::TYPE_PLAY_ROLEID_PLAYER, $key);
        if ($ret2 != "" && $ret2 != $this->playerId) {
            $playerIds[] = $ret2;
        }

        if (empty($playerIds)) {
            return [0 => 0];
        }

        //获取我的好友列表
        $mineList = $this->getMinePlayerIdList();
        $ret = [];
        foreach ($playerIds as $id) {
            if ($id == $this->playerId) {
                continue;
            }
            if (array_key_exists($id, $mineList)) {
                $ret[$id][FriendsData::IS_FRIEND] = true;
            }else{
                $ret[$id][FriendsData::IS_FRIEND] = false;
            }
            //黑名单
            if (array_key_exists($id, $blackList)) {
                $ret[$id][FriendsData::IS_BLACK] = true;
            } else {
                $ret[$id][FriendsData::IS_BLACK] = false;
            }
            $ret[$id][FriendsData::DB_REMARK] = "";
        }
        $ret[0] = count($ret);
        return $ret;
    }

    // 更新备注表
    public function upRemark($remarkName, &$code): bool
    {
        $this->friends->playerId = $this->playerId;
        $this->friends->respondentPlayerId = $this->respondentPlayerId;
        $this->friends->getOneFriend($dbData);
        $this->friends->formateData($dbData);
        $this->friends->remark = $remarkName;
        if (!$this->friends->updateDB()){
            $code = ClientErrorCode::FRIEND_REMARK_FAIL;
            return false;
        }
        $code = ClientErrorCode::CLIENT_SUCCESS;
        return true;
    }

    public function getFriendData(): FriendsData
    {
        $this->friends->playerId = $this->playerId;
        $this->friends->respondentPlayerId = $this->respondentPlayerId;
        $this->friends->getOneFriend($data);
        $this->friends->formateData($data);
        return $this->friends;
    }

    //增加亲密度
    public function addIntimacy(int $addPoint, bool $addTarget)
    {
        $this->friends->playerId = $this->playerId;
        $this->friends->respondentPlayerId = $this->respondentPlayerId;
        $this->friends->getOneFriend($data);
        $this->friends->formateData($data);
        $this->friends->intimacy += $addPoint;
        $this->friends->updateDB();
        //通知亲密度变化
        $this->sendUpdateIntimacyMessage($this->playerId, $this->respondentPlayerId, $this->friends->intimacy);
        if ($addTarget) {
            //更新对方数据
            $this->friends->playerId = $this->respondentPlayerId;
            $this->friends->respondentPlayerId = $this->playerId;
            $this->friends->getOneFriend($data);
            $this->friends->formateData($data);
            $this->friends->intimacy += $addPoint;
            $this->friends->updateDB();
        }
    }

    //设置亲密关系和创建时间
    public function setIntimacyId(int $intimacyId)
    {
        $this->friends->playerId = $this->playerId;
        $this->friends->respondentPlayerId = $this->respondentPlayerId;
        $this->friends->getOneFriend($data);
        $this->friends->formateData($data);
        $this->friends->intimacyId = $intimacyId;
        $this->friends->intimacyCreateTime = Utils::getServerTimestamp();
        $this->friends->updateDB();
        //更新对方数据
        $this->friends->playerId = $this->respondentPlayerId;
        $this->friends->respondentPlayerId = $this->playerId;
        $this->friends->getOneFriend($data);
        $this->friends->formateData($data);
        $this->friends->intimacyId = $intimacyId;
        $this->friends->intimacyCreateTime = Utils::getServerTimestamp();
        $this->friends->updateDB();
    }

    //增加比赛次数 更新小火苗
    //每周有上限 只能升级一次
    public function addIntimacyFire()
    {
        $this->friends->playerId = $this->playerId;
        $this->friends->respondentPlayerId = $this->respondentPlayerId;
        $this->friends->getOneFriend($data);
        $this->friends->formateData($data);
        ++$this->friends->matchNum;
        if ($this->friends->keepFire) {
            $this->friends->updateDB();
            return;
        }
        //检查是否更新小火苗
        if ($this->friends->intimacyIcon == 0) {
            //第一个需要20场比赛
            $needNum = $this->getTerm(
                TemplateDefine::TYPE_CONST,
                TemplateConst::Const_Intimacy_First_Flame_Match_Num,
                TemplateConst::ConstNum);
            if ($this->friends->matchNum >= $needNum) {
                ++$this->friends->intimacyIcon;
                //本周完成场次,保持火苗不消失
                $this->friends->keepFire = true;
            }
        } else {
            $needNum = $this->getTerm(
                TemplateDefine::TYPE_CONST,
                TemplateConst::Const_Intimacy_Flame_To_Match_Num,
                TemplateConst::ConstNum);
            if ($this->friends->matchNum >= $needNum) {
                ++$this->friends->intimacyIcon;
                //本周完成场次,保持火苗不消失
                $this->friends->keepFire = true;
            }
            $maxLevel = (int)$this->getTerm(
                TemplateDefine::TYPE_CONST,
                TemplateConst::Const_Intimacy_Fire_Max_Num,
                TemplateConst::ConstNum);
            if ($this->friends->intimacyIcon >= $maxLevel) {
                $this->friends->intimacyIcon = $maxLevel;
            }
        }
        $this->friends->updateDB();
    }

    //跨周重置 检查小火苗
    public function resetIntimacyFire()
    {
        $this->friends->playerId = $this->playerId;
        if (!$this->friends->getList($result)){
            return;
        }
        if (empty($result)) {
            return;
        }
        foreach ($result as $playerId => $infos) {
            if ($playerId == $this->playerId) {
                continue;
            }
            $info = json_decode($infos, true);
            if ($info[FriendsData::INTIMACY_ICON] == 0) {
                continue;
            }
            //重置数据
            $this->friends->respondentPlayerId = $playerId;
            $this->friends->formateData($info);
            if (!$this->friends->keepFire) {
                --$this->friends->intimacyIcon;
            }
            $this->friends->matchNum = 0;
            $this->friends->keepFire = false;
            $this->friends->updateDB();
        }
    }

    //设置解除亲密关系冷静期
    public function updateIntimacyCDTime(int $cdTime)
    {
        $this->friends->playerId = $this->playerId;
        $this->friends->respondentPlayerId = $this->respondentPlayerId;
        $this->friends->getOneFriend($data);
        $this->friends->formateData($data);
        $this->friends->cdTime = $cdTime;
        if ($cdTime == 0) {
            //解除关系
            $this->friends->intimacyId = 0;
            $this->friends->intimacyCreateTime = 0;
        }
        $this->friends->updateDB();
        //更新对方数据
        $this->friends->playerId = $this->respondentPlayerId;
        $this->friends->respondentPlayerId = $this->playerId;
        $this->friends->getOneFriend($data);
        $this->friends->formateData($data);
        $this->friends->cdTime = $cdTime;
        if ($cdTime == 0) {
            //解除关系
            $this->friends->intimacyId = 0;
            $this->friends->intimacyCreateTime = 0;
        }
        $this->friends->updateDB();
    }

    //通知亲密度变化
    private function sendUpdateIntimacyMessage(int $playerId, int $targetPlayerId, int $intimacy)
    {
        $data = new FriendIntimacy();
        $data->setPlayerId($targetPlayerId);
        $data->setIntimacy($intimacy);
        $message = new GCUpdateFriendIntimacy();
        $message->setIntimacyData([$data]);
        $this->addPacket(PacketId::GC_UpdateFriendIntimacy, $message, $playerId);
        //给对方
        $data = new FriendIntimacy();
        $data->setPlayerId($playerId);
        $data->setIntimacy($intimacy);
        $message = new GCUpdateFriendIntimacy();
        $message->setIntimacyData([$data]);
        $this->addPacket(PacketId::GC_UpdateFriendIntimacy, $message, $targetPlayerId);
    }
}