package net.minecraft.world.level.block.entity;

import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.world.inventory.LecternMenu;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.nbt.Tag;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.phys.Vec2;
import net.minecraft.commands.CommandSource;
import net.minecraft.core.Vec3i;
import net.minecraft.world.phys.Vec3;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.Mth;
import net.minecraft.world.item.WrittenBookItem;
import javax.annotation.Nullable;
import net.minecraft.world.level.block.LecternBlock;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.Items;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.inventory.ContainerData;
import net.minecraft.world.Container;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.Clearable;

public class LecternBlockEntity extends BlockEntity implements Clearable, MenuProvider {
    private final Container bookAccess;
    private final ContainerData dataAccess;
    private ItemStack book;
    private int page;
    private int pageCount;
    
    public LecternBlockEntity() {
        super(BlockEntityType.LECTERN);
        this.bookAccess = new Container() {
            @Override
            public int getContainerSize() {
                return 1;
            }
            
            @Override
            public boolean isEmpty() {
                return LecternBlockEntity.this.book.isEmpty();
            }
            
            @Override
            public ItemStack getItem(final int integer) {
                return (integer == 0) ? LecternBlockEntity.this.book : ItemStack.EMPTY;
            }
            
            @Override
            public ItemStack removeItem(final int integer1, final int integer2) {
                if (integer1 == 0) {
                    final ItemStack bki4 = LecternBlockEntity.this.book.split(integer2);
                    if (LecternBlockEntity.this.book.isEmpty()) {
                        LecternBlockEntity.this.onBookItemRemove();
                    }
                    return bki4;
                }
                return ItemStack.EMPTY;
            }
            
            @Override
            public ItemStack removeItemNoUpdate(final int integer) {
                if (integer == 0) {
                    final ItemStack bki3 = LecternBlockEntity.this.book;
                    LecternBlockEntity.this.book = ItemStack.EMPTY;
                    LecternBlockEntity.this.onBookItemRemove();
                    return bki3;
                }
                return ItemStack.EMPTY;
            }
            
            @Override
            public void setItem(final int integer, final ItemStack bki) {
            }
            
            @Override
            public int getMaxStackSize() {
                return 1;
            }
            
            @Override
            public void setChanged() {
                LecternBlockEntity.this.setChanged();
            }
            
            @Override
            public boolean stillValid(final Player bec) {
                return LecternBlockEntity.this.level.getBlockEntity(LecternBlockEntity.this.worldPosition) == LecternBlockEntity.this && bec.distanceToSqr(LecternBlockEntity.this.worldPosition.getX() + 0.5, LecternBlockEntity.this.worldPosition.getY() + 0.5, LecternBlockEntity.this.worldPosition.getZ() + 0.5) <= 64.0 && LecternBlockEntity.this.hasBook();
            }
            
            @Override
            public boolean canPlaceItem(final int integer, final ItemStack bki) {
                return false;
            }
            
            @Override
            public void clearContent() {
            }
        };
        this.dataAccess = new ContainerData() {
            @Override
            public int get(final int integer) {
                return (integer == 0) ? LecternBlockEntity.this.page : 0;
            }
            
            @Override
            public void set(final int integer1, final int integer2) {
                if (integer1 == 0) {
                    LecternBlockEntity.this.setPage(integer2);
                }
            }
            
            @Override
            public int getCount() {
                return 1;
            }
        };
        this.book = ItemStack.EMPTY;
    }
    
    public ItemStack getBook() {
        return this.book;
    }
    
    public boolean hasBook() {
        final Item bke2 = this.book.getItem();
        return bke2 == Items.WRITABLE_BOOK || bke2 == Items.WRITTEN_BOOK;
    }
    
    public void setBook(final ItemStack bki) {
        this.setBook(bki, null);
    }
    
    private void onBookItemRemove() {
        this.page = 0;
        this.pageCount = 0;
        LecternBlock.resetBookState(this.getLevel(), this.getBlockPos(), this.getBlockState(), false);
    }
    
    public void setBook(final ItemStack bki, @Nullable final Player bec) {
        this.book = this.resolveBook(bki, bec);
        this.page = 0;
        this.pageCount = WrittenBookItem.getPageCount(this.book);
        this.setChanged();
    }
    
    private void setPage(final int integer) {
        final int integer2 = Mth.clamp(integer, 0, this.pageCount - 1);
        if (integer2 != this.page) {
            this.page = integer2;
            this.setChanged();
            LecternBlock.signalPageChange(this.getLevel(), this.getBlockPos(), this.getBlockState());
        }
    }
    
    public int getPage() {
        return this.page;
    }
    
    public int getRedstoneSignal() {
        final float float2 = (this.pageCount > 1) ? (this.getPage() / (this.pageCount - 1.0f)) : 1.0f;
        return Mth.floor(float2 * 14.0f) + (this.hasBook() ? 1 : 0);
    }
    
    private ItemStack resolveBook(final ItemStack bki, @Nullable final Player bec) {
        if (this.level instanceof ServerLevel && bki.getItem() == Items.WRITTEN_BOOK) {
            WrittenBookItem.resolveBookComponents(bki, this.createCommandSourceStack(bec), bec);
        }
        return bki;
    }
    
    private CommandSourceStack createCommandSourceStack(@Nullable final Player bec) {
        String string3;
        Component mr4;
        if (bec == null) {
            string3 = "Lectern";
            mr4 = new TextComponent("Lectern");
        }
        else {
            string3 = bec.getName().getString();
            mr4 = bec.getDisplayName();
        }
        final Vec3 dem5 = Vec3.atCenterOf(this.worldPosition);
        return new CommandSourceStack(CommandSource.NULL, dem5, Vec2.ZERO, (ServerLevel)this.level, 2, string3, mr4, this.level.getServer(), bec);
    }
    
    @Override
    public boolean onlyOpCanSetNbt() {
        return true;
    }
    
    @Override
    public void load(final BlockState cfj, final CompoundTag le) {
        super.load(cfj, le);
        if (le.contains("Book", 10)) {
            this.book = this.resolveBook(ItemStack.of(le.getCompound("Book")), null);
        }
        else {
            this.book = ItemStack.EMPTY;
        }
        this.pageCount = WrittenBookItem.getPageCount(this.book);
        this.page = Mth.clamp(le.getInt("Page"), 0, this.pageCount - 1);
    }
    
    @Override
    public CompoundTag save(final CompoundTag le) {
        super.save(le);
        if (!this.getBook().isEmpty()) {
            le.put("Book", this.getBook().save(new CompoundTag()));
            le.putInt("Page", this.page);
        }
        return le;
    }
    
    @Override
    public void clearContent() {
        this.setBook(ItemStack.EMPTY);
    }
    
    @Override
    public AbstractContainerMenu createMenu(final int integer, final Inventory beb, final Player bec) {
        return new LecternMenu(integer, this.bookAccess, this.dataAccess);
    }
    
    @Override
    public Component getDisplayName() {
        return new TranslatableComponent("container.lectern");
    }
}
