package com.example.demo.module.game;

import com.example.demo.common.GlobalConfig;
import com.example.demo.module.game.data.MatchPlayerInfo;
import com.example.demo.module.game.data.Room;
import com.example.demo.module.rank.RankService;
import com.example.demo.module.user.Player;
import pers.jc.engine.JCEngine;
import pers.jc.network.SocketComponent;
import pers.jc.network.SocketMethod;
import pers.jc.util.JCLogger;

import java.util.*;

/**
 * Socket组件-PK
 */
@SocketComponent("pkComp")
public class PKComp {
    private HashMap<String, Room> roomMap = new HashMap<>();
    private Deque<String > roomKeysToDestroy = new LinkedList<>();

    public PKComp() {
        //自动清除无效的房间
        JCEngine.scheduler.loop(() -> {
            Iterator<Room> iterator = roomMap.values().iterator();
            while (iterator.hasNext()) {
                Room room = iterator.next();
                MatchPlayerInfo roomMasterInfo = room.playerInfoList.get(0);
                if (!roomMasterInfo.player.isValid) {
                    roomKeysToDestroy.addLast(room.key);
                }
            }
            while (!roomKeysToDestroy.isEmpty()) {
                roomMap.remove(roomKeysToDestroy.removeFirst());
                JCLogger.info("房间数", roomMap.size());
            }
        }, 3 * 1000);
    }

    @SocketMethod
    public void randomMatch(Player player, MatchPlayerInfo playerInfo, int gameType) {
        Room matchRoom = null;
        if (!roomMap.isEmpty()) {
            Iterator<Room> iterator = roomMap.values().iterator();
            while (iterator.hasNext()) {
                Room room = iterator.next();
                MatchPlayerInfo roomMasterInfo = room.playerInfoList.get(0);
                if (!room.canRandomMatch) continue;
                if (room.gameType != gameType) continue;
                if (!roomMasterInfo.player.isValid) continue;
                if (roomMasterInfo.playerID == playerInfo.playerID) continue;
                matchRoom = room;
                break;
            }
        }
        if (matchRoom == null) {
            playerInfo.player = player;
            Room room = new Room(playerInfo, gameType, true, null);
            roomMap.put(room.key, room);
        } else {
            RankService.ins.setRoomNeedCalculatePKScore(matchRoom.key);
            roomMap.remove(matchRoom.key);
            playerInfo.player = player;
            matchRoom.playerInfoList.add(playerInfo);
            for (int i = 0; i < matchRoom.playerInfoList.size(); i++) {
                MatchPlayerInfo item = matchRoom.playerInfoList.get(i);
                onGamePKMatchSuccess(item.player, matchRoom.playerInfoList, i, matchRoom.key);
            }
        }
        JCLogger.info("房间数", roomMap.size());
    }

    @SocketMethod
    public void cancelRandomMatch(int playerID) {
        Iterator<Room> iterator = roomMap.values().iterator();
        while (iterator.hasNext()) {
            Room room = iterator.next();
            for (MatchPlayerInfo item : room.playerInfoList) {
                if (item.playerID == playerID) {
                    roomKeysToDestroy.addLast(room.key);
                }
            }
        }
        while (!roomKeysToDestroy.isEmpty()) {
            roomMap.remove(roomKeysToDestroy.removeFirst());
            JCLogger.info("房间数", roomMap.size());
        }
    }

    @SocketMethod
    public void inviteFriendGamePK(
            Player player, MatchPlayerInfo playerInfo, int gameType, int targetID,
            String inviterViewUUID
    ) {
        Player targetPlayer = Player.playerMap.get(targetID);
        if (targetPlayer == null || !targetPlayer.isValid) {
            return;
        }
        playerInfo.player = player;
        Room room = new Room(playerInfo, gameType, false, inviterViewUUID);
        roomMap.put(room.key, room);
        onInviteFriendGamePK(targetPlayer, playerInfo, gameType, room.key);
        JCLogger.info("房间数", roomMap.size());
    }

    @SocketMethod
    public void acceptFriendGamePK(Player player, MatchPlayerInfo playerInfo, String roomKey) {
        Room room = roomMap.get(roomKey);
        if (room == null) return;
        if (!room.key.equals(roomKey)) return;
        roomMap.remove(roomKey);
        playerInfo.player = player;
        room.playerInfoList.add(playerInfo);
        for (int i = 0; i < room.playerInfoList.size(); i++) {
            MatchPlayerInfo item = room.playerInfoList.get(i);
            onGamePKMatchSuccess(item.player, room.playerInfoList, i, room.key);
        }
        JCLogger.info("房间数", roomMap.size());
    }

    @SocketMethod
    public void inviteOtherTryAgainGamePK(
            Player player, MatchPlayerInfo playerInfo, int gameType, int targetID,
            String inviterViewUUID
    ) {
        Player targetPlayer = Player.playerMap.get(targetID);
        if (targetPlayer == null || !targetPlayer.isValid) {
            return;
        }
        playerInfo.player = player;
        Room room = new Room(playerInfo, gameType, false, inviterViewUUID);
        roomMap.put(room.key, room);
        onInviteOtherTryAgainGamePK(targetPlayer, playerInfo, gameType, room.key);
        JCLogger.info("房间数", roomMap.size());
    }

    @SocketMethod
    public void acceptOtherTryAgainGamePK(Player player, MatchPlayerInfo playerInfo, String roomKey) {
        Room room = roomMap.get(roomKey);
        if (room == null) return;
        if (!room.key.equals(roomKey)) return;
        roomMap.remove(roomKey);
        playerInfo.player = player;
        room.playerInfoList.add(playerInfo);
        for (int i = 0; i < room.playerInfoList.size(); i++) {
            MatchPlayerInfo item = room.playerInfoList.get(i);
            onGamePKMatchSuccess(item.player, room.playerInfoList, i, room.key);
        }
        JCLogger.info("房间数", roomMap.size());
    }

    @SocketMethod
    public void rejectPKInvite(Player player, String roomKey) {
        Room room = roomMap.get(roomKey);
        if (room == null) return;
        for (MatchPlayerInfo item: room.playerInfoList) {
            if (item.playerID != player.userID) {
                onRejectPKInvite(item.player, room.inviterViewUUID);
                break;
            }
        }
    }

    //向服务端的请求
    public void onGamePKMatchSuccess(
            Player player, List<MatchPlayerInfo> playerInfoList, int playerIndexInRoom, String roomKey
    ) {
        String pkGamerServer = GlobalConfig.getGamePkWS();
        player.call("PKComp.onGamePKMatchSuccess", playerInfoList, playerIndexInRoom, roomKey, pkGamerServer);
    }

    public void onInviteFriendGamePK(Player player, MatchPlayerInfo playerInfo, int gameType, String roomKey) {
        player.call("PKComp.onInviteFriendGamePK", playerInfo, gameType, roomKey);
    }

    public void onInviteOtherTryAgainGamePK(Player player, MatchPlayerInfo playerInfo, int gameType, String roomKey) {
        player.call("PKComp.onInviteOtherTryAgainGamePK", playerInfo, gameType, roomKey);
    }

    public void onRejectPKInvite(Player player, String inviterViewUUID) {
        player.call("PKComp.onRejectPKInvite", inviterViewUUID);
    }
}
