package net.xevianlight.aphelion.block.custom;

import com.mojang.serialization.MapCodec;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.Mth;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.SimpleMenuProvider;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.BaseEntityBlock;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.phys.BlockHitResult;
import net.neoforged.neoforge.items.ItemStackHandler;
import net.xevianlight.aphelion.block.custom.base.BasicHorizontalEntityBlock;
import net.xevianlight.aphelion.block.entity.custom.VacuumArcFurnaceControllerEntity;
import net.xevianlight.aphelion.util.AphelionBlockStateProperties;
import net.xevianlight.aphelion.util.IMultiblockController;
import net.xevianlight.aphelion.util.MultiblockHelper;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.List;

public class VacuumArcFurnaceController extends BasicHorizontalEntityBlock {

    public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING;
    public static final BooleanProperty LIT = BlockStateProperties.LIT;
    public static final BooleanProperty FORMED = AphelionBlockStateProperties.FORMED;

    public VacuumArcFurnaceController(Properties properties) {
        super(properties, true);
        this.registerDefaultState(this.getStateDefinition().any()
                .setValue(FACING, Direction.NORTH)
                .setValue(LIT, false)
                .setValue(FORMED, false));
    }

    public static final MapCodec<VacuumArcFurnaceController> CODEC = simpleCodec(VacuumArcFurnaceController::new);

    private final int INPUT_SLOT = 0;
    private final int SECONDARY_INPUT_SLOT = 1;
    private final int OUTPUT_SLOT = 2;
    private final int ENERGY_SLOT = 3;

    @Override
    protected MapCodec<? extends BaseEntityBlock> codec() {
        return CODEC;
    }

    public static Properties getProperties() {
        return Properties
                .of()
                .sound(SoundType.NETHERITE_BLOCK)
                .destroyTime(2f)
                .explosionResistance(10f)
                .requiresCorrectToolForDrops()
                .lightLevel(state -> state.getValue(BlockStateProperties.LIT) ? 15 : 0);
    }

    public static Item.Properties getItemProperties() {
        return new Item.Properties();
    }

    @Override
    public @NotNull InteractionResult useWithoutItem(@NotNull BlockState state, Level level, @NotNull BlockPos pos, @NotNull Player player, @NotNull BlockHitResult result) {
        if (!level.isClientSide && player instanceof ServerPlayer serverPlayer && level.getBlockEntity(pos) instanceof VacuumArcFurnaceControllerEntity vacuumArcFurnaceEntity) {
            if (vacuumArcFurnaceEntity.isFormed())
                serverPlayer.openMenu(new SimpleMenuProvider(vacuumArcFurnaceEntity, Component.literal("Vacuum Arc Furnace")), pos);
        }
        return InteractionResult.sidedSuccess(level.isClientSide);
    }



    @Override
    public @Nullable BlockEntity newBlockEntity(@NotNull BlockPos blockPos, @NotNull BlockState blockState) {
        return new VacuumArcFurnaceControllerEntity(blockPos, blockState);
    }

    @Override
    protected void onRemove(BlockState state, Level level, @NotNull BlockPos pos, BlockState newState, boolean movedByPiston) {
        if (!level.isClientSide && state.getBlock() != newState.getBlock()) {
            BlockEntity blockEntity= level.getBlockEntity(pos);
            if (blockEntity instanceof VacuumArcFurnaceControllerEntity vacuumArcFurnaceEntity) {
                if(state.getValue(FORMED)) MultiblockHelper.unformForRemoval(level, state, pos, VacuumArcFurnaceControllerEntity.SHAPE, AphelionBlockStateProperties.FORMED);
                vacuumArcFurnaceEntity.drops();
            }
        }
        super.onRemove(state, level, pos, newState, movedByPiston);
    }

    @Override
    protected void onPlace(BlockState state, Level level, @NotNull BlockPos pos, @NotNull BlockState oldState, boolean movedByPiston) {
        super.onPlace(state, level, pos, oldState, movedByPiston);
        if (!level.isClientSide() && oldState.getBlock() != state.getBlock()) {
            BlockEntity blockEntity= level.getBlockEntity(pos);
            if (blockEntity instanceof IMultiblockController mbController) {
                mbController.markDirty();
            }
        }
    }

    public static int getRedstoneSignalFromItemHandler(@Nullable ItemStackHandler itemStackHandler, List<Integer> slots) {
        if (itemStackHandler == null) {
            return 0;
        } else {
            int i = 0;
            float f = 0.0F;

            for(int slot : slots) {
                ItemStack itemstack = itemStackHandler.getStackInSlot(slot);
                if (!itemstack.isEmpty()) {
                    f += (float)itemstack.getCount() / (float)Math.min(itemStackHandler.getSlotLimit(slot), itemstack.getMaxStackSize());
                    ++i;
                }
            }

            f /= (float)slots.size();
            return Mth.floor(f * 14.0F) + (i > 0 ? 1 : 0);
        }
    }

    @Override
    protected boolean isSignalSource(@NotNull BlockState state) {
        return true;
    }

    @Override
    protected int getSignal(@NotNull BlockState state, @NotNull BlockGetter level, @NotNull BlockPos pos, @NotNull Direction direction) {
        return super.getSignal(state, level, pos, direction);
    }

    @Override
    protected boolean hasAnalogOutputSignal(@NotNull BlockState state) {
        return true;
    }

    @Override
    protected int getAnalogOutputSignal(@NotNull BlockState blockState, Level level, @NotNull BlockPos pos) {
        List<Integer> slots = new ArrayList<>();
        slots.add(VacuumArcFurnaceControllerEntity.INPUT_SLOT);
        slots.add(VacuumArcFurnaceControllerEntity.SECONDARY_INPUT_SLOT);
        slots.add(VacuumArcFurnaceControllerEntity.OUTPUT_SLOT);
        VacuumArcFurnaceControllerEntity vacuumArcFurnaceEntity = ((VacuumArcFurnaceControllerEntity) level.getBlockEntity(pos));

        if (vacuumArcFurnaceEntity != null)
            return getRedstoneSignalFromItemHandler(vacuumArcFurnaceEntity.inventory, slots);

        return 0;
    }

    @Override
    public @Nullable BlockState getStateForPlacement(BlockPlaceContext context) {
        return this.defaultBlockState().setValue(FACING, context.getHorizontalDirection().getOpposite()).setValue(LIT, false).setValue(FORMED, false);
    }

    @Override
    protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
        builder.add(FACING, LIT, FORMED);
    }
}
