// 
// Decompiled by Procyon v0.6.0
// 

package com.hypixel.hytale.protocol;

import java.util.Objects;
import com.hypixel.hytale.protocol.io.ValidationResult;
import com.hypixel.hytale.protocol.io.PacketIO;
import com.hypixel.hytale.protocol.io.ProtocolException;
import com.hypixel.hytale.protocol.io.VarInt;
import io.netty.buffer.ByteBuf;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;

public class BlockTextures
{
    public static final int NULLABLE_BIT_FIELD_SIZE = 1;
    public static final int FIXED_BLOCK_SIZE = 5;
    public static final int VARIABLE_FIELD_COUNT = 6;
    public static final int VARIABLE_BLOCK_START = 29;
    public static final int MAX_SIZE = 98304059;
    @Nullable
    public String top;
    @Nullable
    public String bottom;
    @Nullable
    public String front;
    @Nullable
    public String back;
    @Nullable
    public String left;
    @Nullable
    public String right;
    public float weight;
    
    public BlockTextures() {
    }
    
    public BlockTextures(@Nullable final String top, @Nullable final String bottom, @Nullable final String front, @Nullable final String back, @Nullable final String left, @Nullable final String right, final float weight) {
        this.top = top;
        this.bottom = bottom;
        this.front = front;
        this.back = back;
        this.left = left;
        this.right = right;
        this.weight = weight;
    }
    
    public BlockTextures(@Nonnull final BlockTextures other) {
        this.top = other.top;
        this.bottom = other.bottom;
        this.front = other.front;
        this.back = other.back;
        this.left = other.left;
        this.right = other.right;
        this.weight = other.weight;
    }
    
    @Nonnull
    public static BlockTextures deserialize(@Nonnull final ByteBuf buf, final int offset) {
        final BlockTextures obj = new BlockTextures();
        final byte nullBits = buf.getByte(offset);
        obj.weight = buf.getFloatLE(offset + 1);
        if ((nullBits & 0x1) != 0x0) {
            final int varPos0 = offset + 29 + buf.getIntLE(offset + 5);
            final int topLen = VarInt.peek(buf, varPos0);
            if (topLen < 0) {
                throw ProtocolException.negativeLength("Top", topLen);
            }
            if (topLen > 4096000) {
                throw ProtocolException.stringTooLong("Top", topLen, 4096000);
            }
            obj.top = PacketIO.readVarString(buf, varPos0, PacketIO.UTF8);
        }
        if ((nullBits & 0x2) != 0x0) {
            final int varPos2 = offset + 29 + buf.getIntLE(offset + 9);
            final int bottomLen = VarInt.peek(buf, varPos2);
            if (bottomLen < 0) {
                throw ProtocolException.negativeLength("Bottom", bottomLen);
            }
            if (bottomLen > 4096000) {
                throw ProtocolException.stringTooLong("Bottom", bottomLen, 4096000);
            }
            obj.bottom = PacketIO.readVarString(buf, varPos2, PacketIO.UTF8);
        }
        if ((nullBits & 0x4) != 0x0) {
            final int varPos3 = offset + 29 + buf.getIntLE(offset + 13);
            final int frontLen = VarInt.peek(buf, varPos3);
            if (frontLen < 0) {
                throw ProtocolException.negativeLength("Front", frontLen);
            }
            if (frontLen > 4096000) {
                throw ProtocolException.stringTooLong("Front", frontLen, 4096000);
            }
            obj.front = PacketIO.readVarString(buf, varPos3, PacketIO.UTF8);
        }
        if ((nullBits & 0x8) != 0x0) {
            final int varPos4 = offset + 29 + buf.getIntLE(offset + 17);
            final int backLen = VarInt.peek(buf, varPos4);
            if (backLen < 0) {
                throw ProtocolException.negativeLength("Back", backLen);
            }
            if (backLen > 4096000) {
                throw ProtocolException.stringTooLong("Back", backLen, 4096000);
            }
            obj.back = PacketIO.readVarString(buf, varPos4, PacketIO.UTF8);
        }
        if ((nullBits & 0x10) != 0x0) {
            final int varPos5 = offset + 29 + buf.getIntLE(offset + 21);
            final int leftLen = VarInt.peek(buf, varPos5);
            if (leftLen < 0) {
                throw ProtocolException.negativeLength("Left", leftLen);
            }
            if (leftLen > 4096000) {
                throw ProtocolException.stringTooLong("Left", leftLen, 4096000);
            }
            obj.left = PacketIO.readVarString(buf, varPos5, PacketIO.UTF8);
        }
        if ((nullBits & 0x20) != 0x0) {
            final int varPos6 = offset + 29 + buf.getIntLE(offset + 25);
            final int rightLen = VarInt.peek(buf, varPos6);
            if (rightLen < 0) {
                throw ProtocolException.negativeLength("Right", rightLen);
            }
            if (rightLen > 4096000) {
                throw ProtocolException.stringTooLong("Right", rightLen, 4096000);
            }
            obj.right = PacketIO.readVarString(buf, varPos6, PacketIO.UTF8);
        }
        return obj;
    }
    
    public static int computeBytesConsumed(@Nonnull final ByteBuf buf, final int offset) {
        final byte nullBits = buf.getByte(offset);
        int maxEnd = 29;
        if ((nullBits & 0x1) != 0x0) {
            final int fieldOffset0 = buf.getIntLE(offset + 5);
            int pos0 = offset + 29 + fieldOffset0;
            final int sl = VarInt.peek(buf, pos0);
            pos0 += VarInt.length(buf, pos0) + sl;
            if (pos0 - offset > maxEnd) {
                maxEnd = pos0 - offset;
            }
        }
        if ((nullBits & 0x2) != 0x0) {
            final int fieldOffset2 = buf.getIntLE(offset + 9);
            int pos2 = offset + 29 + fieldOffset2;
            final int sl = VarInt.peek(buf, pos2);
            pos2 += VarInt.length(buf, pos2) + sl;
            if (pos2 - offset > maxEnd) {
                maxEnd = pos2 - offset;
            }
        }
        if ((nullBits & 0x4) != 0x0) {
            final int fieldOffset3 = buf.getIntLE(offset + 13);
            int pos3 = offset + 29 + fieldOffset3;
            final int sl = VarInt.peek(buf, pos3);
            pos3 += VarInt.length(buf, pos3) + sl;
            if (pos3 - offset > maxEnd) {
                maxEnd = pos3 - offset;
            }
        }
        if ((nullBits & 0x8) != 0x0) {
            final int fieldOffset4 = buf.getIntLE(offset + 17);
            int pos4 = offset + 29 + fieldOffset4;
            final int sl = VarInt.peek(buf, pos4);
            pos4 += VarInt.length(buf, pos4) + sl;
            if (pos4 - offset > maxEnd) {
                maxEnd = pos4 - offset;
            }
        }
        if ((nullBits & 0x10) != 0x0) {
            final int fieldOffset5 = buf.getIntLE(offset + 21);
            int pos5 = offset + 29 + fieldOffset5;
            final int sl = VarInt.peek(buf, pos5);
            pos5 += VarInt.length(buf, pos5) + sl;
            if (pos5 - offset > maxEnd) {
                maxEnd = pos5 - offset;
            }
        }
        if ((nullBits & 0x20) != 0x0) {
            final int fieldOffset6 = buf.getIntLE(offset + 25);
            int pos6 = offset + 29 + fieldOffset6;
            final int sl = VarInt.peek(buf, pos6);
            pos6 += VarInt.length(buf, pos6) + sl;
            if (pos6 - offset > maxEnd) {
                maxEnd = pos6 - offset;
            }
        }
        return maxEnd;
    }
    
    public void serialize(@Nonnull final ByteBuf buf) {
        final int startPos = buf.writerIndex();
        byte nullBits = 0;
        if (this.top != null) {
            nullBits |= 0x1;
        }
        if (this.bottom != null) {
            nullBits |= 0x2;
        }
        if (this.front != null) {
            nullBits |= 0x4;
        }
        if (this.back != null) {
            nullBits |= 0x8;
        }
        if (this.left != null) {
            nullBits |= 0x10;
        }
        if (this.right != null) {
            nullBits |= 0x20;
        }
        buf.writeByte(nullBits);
        buf.writeFloatLE(this.weight);
        final int topOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int bottomOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int frontOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int backOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int leftOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int rightOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int varBlockStart = buf.writerIndex();
        if (this.top != null) {
            buf.setIntLE(topOffsetSlot, buf.writerIndex() - varBlockStart);
            PacketIO.writeVarString(buf, this.top, 4096000);
        }
        else {
            buf.setIntLE(topOffsetSlot, -1);
        }
        if (this.bottom != null) {
            buf.setIntLE(bottomOffsetSlot, buf.writerIndex() - varBlockStart);
            PacketIO.writeVarString(buf, this.bottom, 4096000);
        }
        else {
            buf.setIntLE(bottomOffsetSlot, -1);
        }
        if (this.front != null) {
            buf.setIntLE(frontOffsetSlot, buf.writerIndex() - varBlockStart);
            PacketIO.writeVarString(buf, this.front, 4096000);
        }
        else {
            buf.setIntLE(frontOffsetSlot, -1);
        }
        if (this.back != null) {
            buf.setIntLE(backOffsetSlot, buf.writerIndex() - varBlockStart);
            PacketIO.writeVarString(buf, this.back, 4096000);
        }
        else {
            buf.setIntLE(backOffsetSlot, -1);
        }
        if (this.left != null) {
            buf.setIntLE(leftOffsetSlot, buf.writerIndex() - varBlockStart);
            PacketIO.writeVarString(buf, this.left, 4096000);
        }
        else {
            buf.setIntLE(leftOffsetSlot, -1);
        }
        if (this.right != null) {
            buf.setIntLE(rightOffsetSlot, buf.writerIndex() - varBlockStart);
            PacketIO.writeVarString(buf, this.right, 4096000);
        }
        else {
            buf.setIntLE(rightOffsetSlot, -1);
        }
    }
    
    public int computeSize() {
        int size = 29;
        if (this.top != null) {
            size += PacketIO.stringSize(this.top);
        }
        if (this.bottom != null) {
            size += PacketIO.stringSize(this.bottom);
        }
        if (this.front != null) {
            size += PacketIO.stringSize(this.front);
        }
        if (this.back != null) {
            size += PacketIO.stringSize(this.back);
        }
        if (this.left != null) {
            size += PacketIO.stringSize(this.left);
        }
        if (this.right != null) {
            size += PacketIO.stringSize(this.right);
        }
        return size;
    }
    
    public static ValidationResult validateStructure(@Nonnull final ByteBuf buffer, final int offset) {
        if (buffer.readableBytes() - offset < 29) {
            return ValidationResult.error("Buffer too small: expected at least 29 bytes");
        }
        final byte nullBits = buffer.getByte(offset);
        if ((nullBits & 0x1) != 0x0) {
            final int topOffset = buffer.getIntLE(offset + 5);
            if (topOffset < 0) {
                return ValidationResult.error("Invalid offset for Top");
            }
            int pos = offset + 29 + topOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for Top");
            }
            final int topLen = VarInt.peek(buffer, pos);
            if (topLen < 0) {
                return ValidationResult.error("Invalid string length for Top");
            }
            if (topLen > 4096000) {
                return ValidationResult.error("Top exceeds max length 4096000");
            }
            pos += VarInt.length(buffer, pos);
            pos += topLen;
            if (pos > buffer.writerIndex()) {
                return ValidationResult.error("Buffer overflow reading Top");
            }
        }
        if ((nullBits & 0x2) != 0x0) {
            final int bottomOffset = buffer.getIntLE(offset + 9);
            if (bottomOffset < 0) {
                return ValidationResult.error("Invalid offset for Bottom");
            }
            int pos = offset + 29 + bottomOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for Bottom");
            }
            final int bottomLen = VarInt.peek(buffer, pos);
            if (bottomLen < 0) {
                return ValidationResult.error("Invalid string length for Bottom");
            }
            if (bottomLen > 4096000) {
                return ValidationResult.error("Bottom exceeds max length 4096000");
            }
            pos += VarInt.length(buffer, pos);
            pos += bottomLen;
            if (pos > buffer.writerIndex()) {
                return ValidationResult.error("Buffer overflow reading Bottom");
            }
        }
        if ((nullBits & 0x4) != 0x0) {
            final int frontOffset = buffer.getIntLE(offset + 13);
            if (frontOffset < 0) {
                return ValidationResult.error("Invalid offset for Front");
            }
            int pos = offset + 29 + frontOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for Front");
            }
            final int frontLen = VarInt.peek(buffer, pos);
            if (frontLen < 0) {
                return ValidationResult.error("Invalid string length for Front");
            }
            if (frontLen > 4096000) {
                return ValidationResult.error("Front exceeds max length 4096000");
            }
            pos += VarInt.length(buffer, pos);
            pos += frontLen;
            if (pos > buffer.writerIndex()) {
                return ValidationResult.error("Buffer overflow reading Front");
            }
        }
        if ((nullBits & 0x8) != 0x0) {
            final int backOffset = buffer.getIntLE(offset + 17);
            if (backOffset < 0) {
                return ValidationResult.error("Invalid offset for Back");
            }
            int pos = offset + 29 + backOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for Back");
            }
            final int backLen = VarInt.peek(buffer, pos);
            if (backLen < 0) {
                return ValidationResult.error("Invalid string length for Back");
            }
            if (backLen > 4096000) {
                return ValidationResult.error("Back exceeds max length 4096000");
            }
            pos += VarInt.length(buffer, pos);
            pos += backLen;
            if (pos > buffer.writerIndex()) {
                return ValidationResult.error("Buffer overflow reading Back");
            }
        }
        if ((nullBits & 0x10) != 0x0) {
            final int leftOffset = buffer.getIntLE(offset + 21);
            if (leftOffset < 0) {
                return ValidationResult.error("Invalid offset for Left");
            }
            int pos = offset + 29 + leftOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for Left");
            }
            final int leftLen = VarInt.peek(buffer, pos);
            if (leftLen < 0) {
                return ValidationResult.error("Invalid string length for Left");
            }
            if (leftLen > 4096000) {
                return ValidationResult.error("Left exceeds max length 4096000");
            }
            pos += VarInt.length(buffer, pos);
            pos += leftLen;
            if (pos > buffer.writerIndex()) {
                return ValidationResult.error("Buffer overflow reading Left");
            }
        }
        if ((nullBits & 0x20) != 0x0) {
            final int rightOffset = buffer.getIntLE(offset + 25);
            if (rightOffset < 0) {
                return ValidationResult.error("Invalid offset for Right");
            }
            int pos = offset + 29 + rightOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for Right");
            }
            final int rightLen = VarInt.peek(buffer, pos);
            if (rightLen < 0) {
                return ValidationResult.error("Invalid string length for Right");
            }
            if (rightLen > 4096000) {
                return ValidationResult.error("Right exceeds max length 4096000");
            }
            pos += VarInt.length(buffer, pos);
            pos += rightLen;
            if (pos > buffer.writerIndex()) {
                return ValidationResult.error("Buffer overflow reading Right");
            }
        }
        return ValidationResult.OK;
    }
    
    public BlockTextures clone() {
        final BlockTextures copy = new BlockTextures();
        copy.top = this.top;
        copy.bottom = this.bottom;
        copy.front = this.front;
        copy.back = this.back;
        copy.left = this.left;
        copy.right = this.right;
        copy.weight = this.weight;
        return copy;
    }
    
    @Override
    public boolean equals(final Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj instanceof final BlockTextures other) {
            return Objects.equals(this.top, other.top) && Objects.equals(this.bottom, other.bottom) && Objects.equals(this.front, other.front) && Objects.equals(this.back, other.back) && Objects.equals(this.left, other.left) && Objects.equals(this.right, other.right) && this.weight == other.weight;
        }
        return false;
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(this.top, this.bottom, this.front, this.back, this.left, this.right, this.weight);
    }
}
