<?php
/**
 *
 */
namespace Game\Logic;

use Framework\Lib\Utils;
use Framework\MVC\ModelManager;
use Framework\Logic\OnLineLogic;
use Framework\Logic\PacketCacheLogic;
use Game\Config\GameConfig;
use Game\Constant\GameConstantDefine;
use Game\Constant\ModelTypeDefine;
use Game\Data\AccountData;
use Game\Data\Club\ClubData;
use Game\Data\Friends\FriendsData;
use Game\Data\NoticeData;
use Game\Data\ProficiencyData;
use Game\Data\RoleExtData;
use Game\Model\AccountModel;
use Game\Model\Club\ClubModel;
use Game\Model\Friend\FriendBlackModel;
use Game\Model\Friend\FriendIntimacyModel;
use Game\Model\Friend\FriendModel;
use Game\Model\NoticeModel;
use Game\Protobuf\FriendGame;
use Game\Protobuf\FriendNotice;
use Game\Protobuf\FriendRole;
use Game\Protobuf\FriendRoleExt;
use Game\Protobuf\GCFriendIntimacyLoginNotice;
use Game\Protobuf\GCHeartBeatApplyGame;
use Game\Protobuf\GCHeartBeatApplyNotice;
use Game\Protobuf\GCHeartBeatFriendStatusShare;
use Game\Protobuf\GCHeartBeatTips;
use Game\Protobuf\PacketId;
use Google\Protobuf\Internal\Message;

trait NoticeLogic {
    use OnLineLogic;
    use PacketCacheLogic;
    use PaiweiLevelLogic;
    use RankLogic;

    //有来源的在线提示
    public function sendSourceTipsNotice(int $otherPlayerId, int $source, $param): bool
    {
        if (in_array($source, NoticeData::Source_End)){
            return true;
        }
        return $this->tipsNotice($otherPlayerId, NoticeData::Notice_Index_Tips, $param);
    }

    //添加心跳在线提示
    public function tipsNotice(int $otherPlayerId, int $title, array $param): bool
    {
        if ($title == NoticeData::Notice_Index_Tips){
            return $this->sendTipsCachePackage($otherPlayerId, $param);
        }
        return false;
    }

    //获取消息数量
    public function getNoticeNum(int $playerId, int $title): int
    {
        /**
         * @var NoticeModel $notice
         */
        $notice = ModelManager::getInstance()->getModel(ModelTypeDefine::NOTICE);
        return $notice->getNoticeNum($playerId, $title);
    }

    //好友申请与邀请比赛的在线通知--只发送消息,校验在对应功能完成
    public function applyNotice(int $playerId, int $otherPlayerId, int $title, array $param): bool
    {
        $paiWei = $this->getPaiweiLevel();
        $dan = (int)$paiWei->levelId;
        /**
         * @var AccountModel $accountModel
         */
        $accountModel = ModelManager::getInstance()->getModel(ModelTypeDefine::ACCOUNT);

        //添加规则
        /**
         * @var NoticeModel $notice
         */
        $notice = ModelManager::getInstance()->getModel(ModelTypeDefine::NOTICE);
        $notice->setOtherPlayerId($otherPlayerId);
        if (!$notice->addNotice($title)){
            return false;
        }

        $qData = [
            AccountData::DB_RoleId,
            AccountData::DB_HEAD,
            AccountData::DB_LEVEL,
            AccountData::DB_GENDER,
            AccountData::DB_NICK_NAME,
            RoleExtData::DB_MEMBER,
        ];
        $mineRoleInfo = $accountModel->getAccountAttr($qData);
        $ctime = Utils::getServerTimestamp();
        $data = [
            "Time" => $ctime,
            "Dan" => $dan,
            AccountData::DB_RoleId => $mineRoleInfo[AccountData::DB_RoleId],
            AccountData::DB_HEAD => $mineRoleInfo[AccountData::DB_HEAD],
            AccountData::DB_LEVEL => $mineRoleInfo[AccountData::DB_LEVEL],
            AccountData::DB_GENDER => $mineRoleInfo[AccountData::DB_GENDER],
            AccountData::DB_NICK_NAME => $mineRoleInfo[AccountData::DB_NICK_NAME],
            RoleExtData::DB_MEMBER => $mineRoleInfo[RoleExtData::DB_MEMBER],
        ];
        $data = array_merge($data, $param);
        if ($title == NoticeData::Notice_Index_Apply_Friend){
            return $this->sendFriendApplyNoticeCachePackage($playerId,$otherPlayerId, $data);
        }
        if ($title == NoticeData::Notice_Index_Invited_Game){
            return $this->sendFriendGameNoticeCachePackage($playerId, $otherPlayerId, $data);
        }

        return false;
    }

    //好友申请通知
    private function sendFriendApplyNoticeCachePackage($playerId, $otherPlayerId, $data): bool
    {
        $applyNotice = new GCHeartBeatApplyNotice();
        $roles[] = $this->MessageFriendRole($playerId, $data);
        $fNotices[] = $this->MessageFriendNotice($playerId, $data);
        $applyNotice->setInfo($roles);
        $applyNotice->setInfoN($fNotices);
        return $this->addPacket(PacketId::GC_HeartBeatApplyNotice, $applyNotice, $otherPlayerId);
    }

    //邀请比赛通知
    private function sendFriendGameNoticeCachePackage($playerId, $otherPlayerId, $data): bool
    {
        $applyGame = new GCHeartBeatApplyGame();
        $roles[] = $this->MessageFriendRole($playerId, $data);
        $applyGame->setInfo($roles);
        $fNotices = $this->MessageFriendNotice($playerId, $data);
        $fGame = new FriendGame();
        $fGame->setGameType($data["GameType"]);
        $fGame->setRoomId($data["RoomId"]);
        $fGame->setInfoExt($fNotices);
        $fGame->setRoomType($data["RoomType"]);
        $fGames[] = $fGame;
        $applyGame->setInfoG($fGames);
        return $this->addPacket(PacketId::GC_HeartBeatApplyGame, $applyGame, $otherPlayerId);
    }

    private function sendTipsCachePackage($otherPlayerId, $data): bool
    {
        $tips = new GCHeartBeatTips();
        $idList[] = $data["TipsId"];
        $tips->setTipsId($idList);
        return $this->addPacket(PacketId::GC_HeartBeatTips, $tips, $otherPlayerId);
    }

    public function delNotice(int $otherPlayerId, int $Index): bool
    {
        /**
         * @var NoticeModel $notice
         */
        $notice = ModelManager::getInstance()->getModel(ModelTypeDefine::NOTICE);
        $notice->dbIndex = $Index;
        $notice->setOtherPlayerId($otherPlayerId);
        return $notice->delNotice();
    }

    private function MessageFriendRole($otherPlayerId, $info)
    {
        $role = new FriendRole();
        $role->setPlayerId($otherPlayerId);
        $role->setRoleId((int)$info[AccountData::DB_RoleId]);
        $role->setLevel((int)$info[AccountData::DB_LEVEL]);
        $role->setMember((int)$info[RoleExtData::DB_MEMBER]);
        $role->setNickName($info[AccountData::DB_NICK_NAME]);
        $role->setGender((int)$info[AccountData::DB_GENDER]);
        $role->setHead((int)$info[AccountData::DB_HEAD]);
        $role->setDan((int)$info["Dan"]);
        return $role;
    }

    private function MessageFriendNotice($otherPlayerId, $info)
    {
        $fNotice = new FriendNotice();
        $fNotice->setPlayerId($otherPlayerId);
        $fNotice->setTime($info["Time"]);
        $fNotice->setSource($info["Source"]);
        return $fNotice;
    }

    //状态更新后同步结果到所有好友心跳列表中
    public function syncFriendStatusToAll(int $status, $playerId)
    {
        /**
         * @var FriendModel $friend
         */
        $friend = ModelManager::getInstance()->getModel(ModelTypeDefine::FRIEND);
        $friend->setPlayerId($playerId);
        //获取好友列表
        $myFriendList = $friend->getMineList();
        if (empty($myFriendList)) {
            return;
        }
        $paiWei = $this->getPaiweiLevel($playerId);
        $param = [
            AccountData::DB_LEVEL,
            AccountData::DB_RoleId,
            AccountData::DB_NICK_NAME,
            AccountData::DB_HEAD,
            AccountData::DB_GENDER,
            RoleExtData::DB_MEMBER,
            AccountData::DB_LOGIN_TIME,
            AccountData::DB_LOGOUT_TIME,
            RoleExtData::DB_FRIEND_REJECT,
            ProficiencyData::PROFICIENCY_LV,
        ];
        $myData = $this->getPlayerData($playerId, $param);
        $myData[RoleExtData::DB_Status] = $status;
        //通用信息
        $roleData = new FriendRole();
        $roleData->setLevel($myData[AccountData::DB_LEVEL]);
        $roleData->setPlayerId($playerId);
        $roleData->setHead(($myData[AccountData::DB_HEAD]));
        $roleData->setGender($myData[AccountData::DB_GENDER]);
        $roleData->setNickName($myData[AccountData::DB_NICK_NAME]);
        $roleData->setMember($myData[RoleExtData::DB_MEMBER]);
        $roleData->setDan($paiWei->levelId);
        $roleData->setRoleId($myData[AccountData::DB_RoleId]);
        $roleExtData = new FriendRoleExt();
        $roleExtData->setPlayerId($playerId);
        $roleExtData->setIndex(1);
        $roleExtData->setOnline($status);
        $roleExtData->setOffLineTime($myData[AccountData::DB_LOGOUT_TIME]);
        $roleExtData->setIsFriend(true);
        /**
         * @var FriendBlackModel $black
         */
        $black = ModelManager::getInstance()->getModel(ModelTypeDefine::FRIEND_BLACK);
        $black->setRespondentPlayerId($playerId);
        $friend->setRespondentPlayerId($playerId);
        //整理信息
        foreach ($myFriendList as $pId => $playerData){
            //检查好友是否在线
            if ($this->getPlayerData($pId, [RoleExtData::DB_Status])[RoleExtData::DB_Status] == GameConstantDefine::PLAYER_STATUS_OFFLINE){
                continue;
            }
            //查询好友信息
            $friend->setPlayerId($pId);
            $friendData = $friend->getFriendData();
            //和好友的亲密关系
            $roleData->setIntimacy($playerData[FriendsData::INTIMACY]);
            $roleData->setCDTime($playerData[FriendsData::CD_TIME]);
            $roleData->setIntimacyIcon($playerData[FriendsData::INTIMACY_ICON]);
            $roleData->setIntimacyCreateTime($playerData[FriendsData::INTIMACY_CREATE_TIME]);
            $roleData->setIntimacyId($playerData[FriendsData::INTIMACY_ID]);
            //别人对自己的备注!!!
            $roleExtData->setRemark($friendData->remark);
            //检查对方是否拉黑自己
            $black->setPlayerId($pId);
            $roleExtData->setIsBlack($black->checkInBlack());
            //别人对自己的点赞信息
            $goodList = array();
            $this->getRankLike($goodList, $pId);
            $roleExtData->setGood(in_array($playerId, $goodList));
            $message = new GCHeartBeatFriendStatusShare();
            $message->setInfo([$roleData]);
            $message->setInfoExt([$roleExtData]);
            $this->addPacket(PacketId::GC_HeartBeatFriendStatusShare, $message, $pId);
        }
    }

    private function getPlayerData(int $playerId, array $keys): array
    {
        /**
         * @var AccountModel $accountModel
         */
        $accountModel = ModelManager::getInstance()->getModel(ModelTypeDefine::ACCOUNT);
        $playerInfo = array();
        $ret = array();
        if ($accountModel->search($playerId, $playerInfo)) {
            foreach ($keys as $key) {
                $ret[$key] = $playerInfo[$key] ?? null;
            }
        }
        return $ret;
    }

    //更新自己的信息到俱乐部成员
    public function updateClubPlayerNotice($status): bool
    {
        /**
         * @var ClubModel $club
         */
        $club = ModelManager::getInstance()->getModel(ModelTypeDefine::CLUB);
        $clubPlayerInfo = $club->getMineClubData(ClubData::PLAYER_INFO, []);
        if (count($clubPlayerInfo) <= 1){
            return false;
        }
        $clubPlayer = $club->clubPlayerMessage($this->playerId, GameConfig::getInstance()->SERVER_ID());
        foreach ($clubPlayerInfo as $playerId => $info){
            if ($playerId == $this->playerId){
                continue;
            }
            if ($this->getPlayerData($playerId, [RoleExtData::DB_Status])[RoleExtData::DB_Status] == GameConstantDefine::PLAYER_STATUS_OFFLINE){
                continue;
            }

            $club->GCUpdateClubPlayer($playerId, $status, $clubPlayer);
        }
        return true;
    }

    //通知亲密关系好友我上线了
    //$accountInfo 自己信息
    public function syncFriendIntimacyLoginNotice(int $playerId, array $accountInfo)
    {
        /**
         * @var FriendIntimacyModel $friendIntimacyModel
         */
        $friendIntimacyModel = ModelManager::getInstance()->getModel(ModelTypeDefine::FRIEND_INTIMACY);
        $friendIntimacyModel->setRespondentPlayerId($playerId);
        $allIntimacy = $friendIntimacyModel->getAllMyIntimacy();
        if (empty($allIntimacy)) {
            return;
        }
        $message = new GCFriendIntimacyLoginNotice();
        $message->setPlayerId($playerId);
        $message->setNickName($accountInfo[AccountData::DB_NICK_NAME]);
        foreach ($allIntimacy as $targetPlayerId => $intimacyId) {
            $message->setIntimacyId($intimacyId);
            $this->addPacket(
                PacketId::GC_FriendIntimacyLoginNotice,
                $message,
                $targetPlayerId
            );
        }
    }

}