/*
 *    This file is a part of the SteamWar software.
 *
 *    Copyright (C) 2022  SteamWar.de-Serverteam
 *
 *    This program is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU Affero General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *    GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

package de.steamwar.core;

import com.comphenix.tinyprotocol.Reflection;
import com.mojang.authlib.GameProfile;
import org.bukkit.GameMode;

import java.util.Collections;
import java.util.EnumMap;
import java.util.List;

public class ProtocolWrapper8 implements ProtocolWrapper {

    private static final Reflection.FieldAccessor<?> equipmentSlot;
    static {
        if(Core.getVersion() == 8) {
            equipmentSlot =  Reflection.getField(equipmentPacket, int.class, 1);
        } else {
            Class<?> enumItemSlot = Reflection.getClass("{nms.world.entity}.EnumItemSlot");
            equipmentSlot =  Reflection.getField(equipmentPacket, enumItemSlot, 0);
        }
    }

    private static final Reflection.FieldAccessor<?> equipmentStack = Reflection.getField(equipmentPacket, itemStack, 0);
    @Override
    public void setEquipmentPacketStack(Object packet, Object slot, Object stack) {
        equipmentSlot.set(packet, slot);
        equipmentStack.set(packet, stack);
    }

    private static final Class<?> playerInfoPacket = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutPlayerInfo");
    private static final Class<?> playerInfoActionClass = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutPlayerInfo$EnumPlayerInfoAction");
    private static final Reflection.FieldAccessor<?> playerInfoAction = Reflection.getField(playerInfoPacket, playerInfoActionClass, 0);
    private static final Reflection.FieldAccessor<List> playerInfoData = Reflection.getField(playerInfoPacket, List.class, 0);
    private static final EnumMap<PlayerInfoAction, Object> actions = new EnumMap<>(PlayerInfoAction.class);
    static {
        Object[] nativeActions = playerInfoActionClass.getEnumConstants();
        actions.put(PlayerInfoAction.ADD, nativeActions[0]);
        actions.put(PlayerInfoAction.GAMEMODE, nativeActions[1]);
        actions.put(PlayerInfoAction.REMOVE, nativeActions[4]);
    }
    private static final Class<?> iChatBaseComponent = Reflection.getClass("{nms.network.chat}.IChatBaseComponent");
    private static final Reflection.ConstructorInvoker playerInfoDataConstructor = Reflection.getConstructor("{nms.network.protocol.game}.PacketPlayOutPlayerInfo$PlayerInfoData", playerInfoPacket, GameProfile.class, int.class, enumGamemode, iChatBaseComponent);

    @Override
    @SuppressWarnings("deprecation")
    public Object playerInfoPacketConstructor(PlayerInfoAction action, GameProfile profile, GameMode mode) {
        Object packet = Reflection.newInstance(playerInfoPacket);
        playerInfoAction.set(packet, actions.get(action));
        playerInfoData.set(packet, Collections.singletonList(playerInfoDataConstructor.invoke(packet, profile, 0, ProtocolWrapper.getGameModeById.invoke(null, mode.getValue()), null)));
        return packet;
    }
}
