/*
 *  Copyright 2025-2026 R3944Realms
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package top.r3944realms.eroticdungeongame.core.compat;

import net.minecraft.client.Minecraft;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.ClipContext;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.client.event.InputEvent;
import net.minecraftforge.client.event.RegisterKeyMappingsEvent;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.network.NetworkEvent;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import top.r3944realms.eroticdungeongame.EroticDungeon;
import top.r3944realms.eroticdungeongame.api.workspace.Services;
import top.r3944realms.eroticdungeongame.client.EDGKeyBindings;
import top.r3944realms.eroticdungeongame.content.block.blockentity.BaseSeatBlockEntity;
import top.r3944realms.eroticdungeongame.content.util.FurnitureHelper;
import top.r3944realms.eroticdungeongame.core.network.EDGNetworkHandler;
import top.r3944realms.lib39.core.compat.ICompat;
import top.r3944realms.superleadrope.api.SuperLeadRopeApi;
import top.r3944realms.superleadrope.api.type.util.ILeashHelper;

import java.util.function.Supplier;

public class SuperLeadRopeCompat implements ICompat {
    public static SuperLeadRopeCompat INSTANCE = new SuperLeadRopeCompat();
    public static ResourceLocation ID = EroticDungeon.rl("superleadrope");

    public boolean initialize = false;
    @Override
    public void setInitialize(boolean initialize) {
        this.initialize = initialize;
    }

    @Override
    public boolean isInitialized() {
        return initialize;
    }
    @Override
    public ResourceLocation id() {
        return ID;
    }

    @Override
    public void initialize() {
        EDGNetworkHandler.CHANNEL.messageBuilder(
                SuperLeadRopeCompat.LeashBindPacket.class
                , EDGNetworkHandler.getIndex()
        )
                .encoder(LeashBindPacket::encode)
                .decoder(LeashBindPacket::decode)
                .consumerMainThread(LeashBindPacket::handle)
                .add();
    }

    @Override
    public void addClientGameListener(@NotNull IEventBus modBus) {
        modBus.addListener(this::onKetBoardInput);
    }

    @Override
    public void addClientModListener(@NotNull IEventBus modBus) {
        modBus.addListener(this::onRegisterKeyBind);
    }

    @Override
    public boolean isModLoaded() {
        return ModList.get().isLoaded("superleadrope");
    }

    @OnlyIn(Dist.CLIENT)
    private void onRegisterKeyBind(RegisterKeyMappingsEvent event) {
        event.register(EDGKeyBindings.KEY_BIND);
    }

    @OnlyIn(Dist.CLIENT)
    public void onKetBoardInput(InputEvent.Key event) {
        Minecraft minecraft = Minecraft.getInstance();
        LocalPlayer player = minecraft.player;
        if(player == null) return;
        if (EDGKeyBindings.KEY_BIND.isDown()) {
            if (minecraft.level != null) {
                Vec3 startPos = player.getEyePosition();
                Vec3 endPos = player.getLookAngle().normalize().scale(5).add(startPos);
                BlockHitResult clip = minecraft.level.clip(new ClipContext(startPos, endPos, ClipContext.Block.VISUAL, ClipContext.Fluid.NONE, player));
                BlockPos blockPos = clip.getBlockPos();
                BlockEntity blockEntity = FurnitureHelper.getSeatBlockEntity(minecraft.level, blockPos);
                if (blockEntity instanceof BaseSeatBlockEntity be && !Services.WORK_SPACE.isInDevice(player)) {
                    EDGNetworkHandler.CHANNEL.sendToServer(new LeashBindPacket(blockPos));
                }
            }

        }
    }
    public record LeashBindPacket(BlockPos lookPos) {
        public static void encode(@NotNull LeashBindPacket packet, @NotNull FriendlyByteBuf buf) {
            buf.writeBlockPos(packet.lookPos);
        }
        @Contract("_ -> new")
        public static @NotNull LeashBindPacket decode(@NotNull FriendlyByteBuf buf) {
            return new LeashBindPacket(buf.readBlockPos());
        }
        public static void handle(LeashBindPacket packet, @NotNull Supplier<NetworkEvent.Context> context) {
            NetworkEvent.Context context1 = context.get();
            ServerPlayer sender = context1.getSender();
            Services.WORK_SPACE.tryToDoIfInDevice(
                    sender,
                    data -> {},
                    () -> {
                        if (sender != null) {
                            BaseSeatBlockEntity seatBlockEntity = FurnitureHelper.getSeatBlockEntity(sender.serverLevel(), packet.lookPos);
                            if (seatBlockEntity != null) {
                                ILeashHelper.IHolder holderHelper = SuperLeadRopeApi.getLeashHelper().getHolderHelper(sender);
                                for (Entity leashedEntity : holderHelper.getAllLeashedEntities()) {
                                    if (leashedEntity instanceof Player player) {
                                        if (holderHelper.unleashEntity(leashedEntity)) {
                                            seatBlockEntity.bindPlayerToSeat(sender.level(), packet.lookPos, sender.level().getBlockState(packet.lookPos), player);
                                            break;
                                        }

                                    }
                                }
                            }
                        }

                    }
            );
            context1.setPacketHandled(true);
        }
    }


}
