package org.bukkit.craftbukkit.v1_20_R3.block;

import com.google.common.base.Preconditions;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.block.entity.DecoratedPotBlockEntity;
import org.bukkit.Material;
import org.bukkit.Tag;
import org.bukkit.World;
import org.bukkit.block.DecoratedPot;
import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftInventoryDecoratedPot;
import org.bukkit.craftbukkit.v1_20_R3.util.CraftMagicNumbers;
import org.bukkit.inventory.DecoratedPotInventory;

public class CraftDecoratedPot extends CraftBlockEntityState<DecoratedPotBlockEntity> implements DecoratedPot {

    public CraftDecoratedPot(World world, DecoratedPotBlockEntity tileEntity) {
        super(world, tileEntity);
    }

    protected CraftDecoratedPot(CraftDecoratedPot state) {
        super(state);
    }

    @Override
    public DecoratedPotInventory getSnapshotInventory() {
        return new CraftInventoryDecoratedPot(this.getSnapshot());
    }

    @Override
    public DecoratedPotInventory getInventory() {
        if (!this.isPlaced()) {
            return this.getSnapshotInventory();
        }

        return new CraftInventoryDecoratedPot(this.getTileEntity());
    }

    @Override
    public void setSherd(Side face, Material sherd) {
        Preconditions.checkArgument(face != null, "face must not be null");
        Preconditions.checkArgument(sherd == null || sherd == Material.BRICK || Tag.ITEMS_DECORATED_POT_SHERDS.isTagged(sherd), "sherd is not a valid sherd material: %s", sherd);

        Item sherdItem = (sherd != null) ? CraftMagicNumbers.getItem(sherd) : Items.BRICK;
        DecoratedPotBlockEntity.Decorations decorations = this.getSnapshot().getDecorations();

        switch (face) {
            case BACK -> this.getSnapshot().decorations = new DecoratedPotBlockEntity.Decorations(sherdItem, decorations.left(), decorations.right(), decorations.front());
            case LEFT -> this.getSnapshot().decorations = new DecoratedPotBlockEntity.Decorations(decorations.back(), sherdItem, decorations.right(), decorations.front());
            case RIGHT -> this.getSnapshot().decorations = new DecoratedPotBlockEntity.Decorations(decorations.back(), decorations.left(), sherdItem, decorations.front());
            case FRONT -> this.getSnapshot().decorations = new DecoratedPotBlockEntity.Decorations(decorations.back(), decorations.left(), decorations.right(), sherdItem);
            default -> throw new IllegalArgumentException("Unexpected value: " + face);
        }
    }

    @Override
    public Material getSherd(Side face) {
        Preconditions.checkArgument(face != null, "face must not be null");

        DecoratedPotBlockEntity.Decorations decorations = this.getSnapshot().getDecorations();
        Item sherdItem = switch (face) {
            case BACK -> decorations.back();
            case LEFT -> decorations.left();
            case RIGHT -> decorations.right();
            case FRONT -> decorations.front();
            default -> throw new IllegalArgumentException("Unexpected value: " + face);
        };

        return CraftMagicNumbers.getMaterial(sherdItem);
    }

    @Override
    public Map<Side, Material> getSherds() {
        DecoratedPotBlockEntity.Decorations decorations = this.getSnapshot().getDecorations();

        Map<Side, Material> sherds = new EnumMap<>(Side.class);
        sherds.put(Side.BACK, CraftMagicNumbers.getMaterial(decorations.back()));
        sherds.put(Side.LEFT, CraftMagicNumbers.getMaterial(decorations.left()));
        sherds.put(Side.RIGHT, CraftMagicNumbers.getMaterial(decorations.right()));
        sherds.put(Side.FRONT, CraftMagicNumbers.getMaterial(decorations.front()));
        return sherds;
    }

    @Override
    public List<Material> getShards() {
        return this.getSnapshot().getDecorations().sorted().map(CraftMagicNumbers::getMaterial).collect(Collectors.toUnmodifiableList());
    }

    @Override
    public CraftDecoratedPot copy() {
        return new CraftDecoratedPot(this);
    }
}
