package net.minecraft.network.protocol.game;

import net.minecraft.network.PacketListener;
import java.io.IOException;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.level.border.WorldBorder;
import net.minecraft.network.protocol.Packet;

public class ClientboundSetBorderPacket implements Packet<ClientGamePacketListener> {
    private Type type;
    private int newAbsoluteMaxSize;
    private double newCenterX;
    private double newCenterZ;
    private double newSize;
    private double oldSize;
    private long lerpTime;
    private int warningTime;
    private int warningBlocks;
    
    public ClientboundSetBorderPacket() {
    }
    
    public ClientboundSetBorderPacket(final WorldBorder cgw, final Type a) {
        this.type = a;
        this.newCenterX = cgw.getCenterX();
        this.newCenterZ = cgw.getCenterZ();
        this.oldSize = cgw.getSize();
        this.newSize = cgw.getLerpTarget();
        this.lerpTime = cgw.getLerpRemainingTime();
        this.newAbsoluteMaxSize = cgw.getAbsoluteMaxSize();
        this.warningBlocks = cgw.getWarningBlocks();
        this.warningTime = cgw.getWarningTime();
    }
    
    @Override
    public void read(final FriendlyByteBuf mg) throws IOException {
        this.type = mg.<Type>readEnum(Type.class);
        switch (this.type) {
            case SET_SIZE: {
                this.newSize = mg.readDouble();
                break;
            }
            case LERP_SIZE: {
                this.oldSize = mg.readDouble();
                this.newSize = mg.readDouble();
                this.lerpTime = mg.readVarLong();
                break;
            }
            case SET_CENTER: {
                this.newCenterX = mg.readDouble();
                this.newCenterZ = mg.readDouble();
                break;
            }
            case SET_WARNING_BLOCKS: {
                this.warningBlocks = mg.readVarInt();
                break;
            }
            case SET_WARNING_TIME: {
                this.warningTime = mg.readVarInt();
                break;
            }
            case INITIALIZE: {
                this.newCenterX = mg.readDouble();
                this.newCenterZ = mg.readDouble();
                this.oldSize = mg.readDouble();
                this.newSize = mg.readDouble();
                this.lerpTime = mg.readVarLong();
                this.newAbsoluteMaxSize = mg.readVarInt();
                this.warningBlocks = mg.readVarInt();
                this.warningTime = mg.readVarInt();
                break;
            }
        }
    }
    
    @Override
    public void write(final FriendlyByteBuf mg) throws IOException {
        mg.writeEnum(this.type);
        switch (this.type) {
            case SET_SIZE: {
                mg.writeDouble(this.newSize);
                break;
            }
            case LERP_SIZE: {
                mg.writeDouble(this.oldSize);
                mg.writeDouble(this.newSize);
                mg.writeVarLong(this.lerpTime);
                break;
            }
            case SET_CENTER: {
                mg.writeDouble(this.newCenterX);
                mg.writeDouble(this.newCenterZ);
                break;
            }
            case SET_WARNING_TIME: {
                mg.writeVarInt(this.warningTime);
                break;
            }
            case SET_WARNING_BLOCKS: {
                mg.writeVarInt(this.warningBlocks);
                break;
            }
            case INITIALIZE: {
                mg.writeDouble(this.newCenterX);
                mg.writeDouble(this.newCenterZ);
                mg.writeDouble(this.oldSize);
                mg.writeDouble(this.newSize);
                mg.writeVarLong(this.lerpTime);
                mg.writeVarInt(this.newAbsoluteMaxSize);
                mg.writeVarInt(this.warningBlocks);
                mg.writeVarInt(this.warningTime);
                break;
            }
        }
    }
    
    @Override
    public void handle(final ClientGamePacketListener nl) {
        nl.handleSetBorder(this);
    }
    
    public void applyChanges(final WorldBorder cgw) {
        switch (this.type) {
            case SET_SIZE: {
                cgw.setSize(this.newSize);
                break;
            }
            case LERP_SIZE: {
                cgw.lerpSizeBetween(this.oldSize, this.newSize, this.lerpTime);
                break;
            }
            case SET_CENTER: {
                cgw.setCenter(this.newCenterX, this.newCenterZ);
                break;
            }
            case INITIALIZE: {
                cgw.setCenter(this.newCenterX, this.newCenterZ);
                if (this.lerpTime > 0L) {
                    cgw.lerpSizeBetween(this.oldSize, this.newSize, this.lerpTime);
                }
                else {
                    cgw.setSize(this.newSize);
                }
                cgw.setAbsoluteMaxSize(this.newAbsoluteMaxSize);
                cgw.setWarningBlocks(this.warningBlocks);
                cgw.setWarningTime(this.warningTime);
                break;
            }
            case SET_WARNING_TIME: {
                cgw.setWarningTime(this.warningTime);
                break;
            }
            case SET_WARNING_BLOCKS: {
                cgw.setWarningBlocks(this.warningBlocks);
                break;
            }
        }
    }
    
    public enum Type {
        SET_SIZE, 
        LERP_SIZE, 
        SET_CENTER, 
        INITIALIZE, 
        SET_WARNING_TIME, 
        SET_WARNING_BLOCKS;
    }
}
