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

package com.hypixel.hytale.protocol.packets.inventory;

import java.util.Objects;
import com.hypixel.hytale.protocol.io.ValidationResult;
import io.netty.buffer.ByteBuf;
import javax.annotation.Nonnull;
import com.hypixel.hytale.protocol.SortType;
import javax.annotation.Nullable;
import com.hypixel.hytale.protocol.InventorySection;
import com.hypixel.hytale.protocol.Packet;

public class UpdatePlayerInventory implements Packet
{
    public static final int PACKET_ID = 170;
    public static final boolean IS_COMPRESSED = true;
    public static final int NULLABLE_BIT_FIELD_SIZE = 1;
    public static final int FIXED_BLOCK_SIZE = 2;
    public static final int VARIABLE_FIELD_COUNT = 7;
    public static final int VARIABLE_BLOCK_START = 30;
    public static final int MAX_SIZE = 1677721600;
    @Nullable
    public InventorySection storage;
    @Nullable
    public InventorySection armor;
    @Nullable
    public InventorySection hotbar;
    @Nullable
    public InventorySection utility;
    @Nullable
    public InventorySection builderMaterial;
    @Nullable
    public InventorySection tools;
    @Nullable
    public InventorySection backpack;
    @Nonnull
    public SortType sortType;
    
    @Override
    public int getId() {
        return 170;
    }
    
    public UpdatePlayerInventory() {
        this.sortType = SortType.Name;
    }
    
    public UpdatePlayerInventory(@Nullable final InventorySection storage, @Nullable final InventorySection armor, @Nullable final InventorySection hotbar, @Nullable final InventorySection utility, @Nullable final InventorySection builderMaterial, @Nullable final InventorySection tools, @Nullable final InventorySection backpack, @Nonnull final SortType sortType) {
        this.sortType = SortType.Name;
        this.storage = storage;
        this.armor = armor;
        this.hotbar = hotbar;
        this.utility = utility;
        this.builderMaterial = builderMaterial;
        this.tools = tools;
        this.backpack = backpack;
        this.sortType = sortType;
    }
    
    public UpdatePlayerInventory(@Nonnull final UpdatePlayerInventory other) {
        this.sortType = SortType.Name;
        this.storage = other.storage;
        this.armor = other.armor;
        this.hotbar = other.hotbar;
        this.utility = other.utility;
        this.builderMaterial = other.builderMaterial;
        this.tools = other.tools;
        this.backpack = other.backpack;
        this.sortType = other.sortType;
    }
    
    @Nonnull
    public static UpdatePlayerInventory deserialize(@Nonnull final ByteBuf buf, final int offset) {
        final UpdatePlayerInventory obj = new UpdatePlayerInventory();
        final byte nullBits = buf.getByte(offset);
        obj.sortType = SortType.fromValue(buf.getByte(offset + 1));
        if ((nullBits & 0x1) != 0x0) {
            final int varPos0 = offset + 30 + buf.getIntLE(offset + 2);
            obj.storage = InventorySection.deserialize(buf, varPos0);
        }
        if ((nullBits & 0x2) != 0x0) {
            final int varPos2 = offset + 30 + buf.getIntLE(offset + 6);
            obj.armor = InventorySection.deserialize(buf, varPos2);
        }
        if ((nullBits & 0x4) != 0x0) {
            final int varPos3 = offset + 30 + buf.getIntLE(offset + 10);
            obj.hotbar = InventorySection.deserialize(buf, varPos3);
        }
        if ((nullBits & 0x8) != 0x0) {
            final int varPos4 = offset + 30 + buf.getIntLE(offset + 14);
            obj.utility = InventorySection.deserialize(buf, varPos4);
        }
        if ((nullBits & 0x10) != 0x0) {
            final int varPos5 = offset + 30 + buf.getIntLE(offset + 18);
            obj.builderMaterial = InventorySection.deserialize(buf, varPos5);
        }
        if ((nullBits & 0x20) != 0x0) {
            final int varPos6 = offset + 30 + buf.getIntLE(offset + 22);
            obj.tools = InventorySection.deserialize(buf, varPos6);
        }
        if ((nullBits & 0x40) != 0x0) {
            final int varPos7 = offset + 30 + buf.getIntLE(offset + 26);
            obj.backpack = InventorySection.deserialize(buf, varPos7);
        }
        return obj;
    }
    
    public static int computeBytesConsumed(@Nonnull final ByteBuf buf, final int offset) {
        final byte nullBits = buf.getByte(offset);
        int maxEnd = 30;
        if ((nullBits & 0x1) != 0x0) {
            final int fieldOffset0 = buf.getIntLE(offset + 2);
            int pos0 = offset + 30 + fieldOffset0;
            pos0 += InventorySection.computeBytesConsumed(buf, pos0);
            if (pos0 - offset > maxEnd) {
                maxEnd = pos0 - offset;
            }
        }
        if ((nullBits & 0x2) != 0x0) {
            final int fieldOffset2 = buf.getIntLE(offset + 6);
            int pos2 = offset + 30 + fieldOffset2;
            pos2 += InventorySection.computeBytesConsumed(buf, pos2);
            if (pos2 - offset > maxEnd) {
                maxEnd = pos2 - offset;
            }
        }
        if ((nullBits & 0x4) != 0x0) {
            final int fieldOffset3 = buf.getIntLE(offset + 10);
            int pos3 = offset + 30 + fieldOffset3;
            pos3 += InventorySection.computeBytesConsumed(buf, pos3);
            if (pos3 - offset > maxEnd) {
                maxEnd = pos3 - offset;
            }
        }
        if ((nullBits & 0x8) != 0x0) {
            final int fieldOffset4 = buf.getIntLE(offset + 14);
            int pos4 = offset + 30 + fieldOffset4;
            pos4 += InventorySection.computeBytesConsumed(buf, pos4);
            if (pos4 - offset > maxEnd) {
                maxEnd = pos4 - offset;
            }
        }
        if ((nullBits & 0x10) != 0x0) {
            final int fieldOffset5 = buf.getIntLE(offset + 18);
            int pos5 = offset + 30 + fieldOffset5;
            pos5 += InventorySection.computeBytesConsumed(buf, pos5);
            if (pos5 - offset > maxEnd) {
                maxEnd = pos5 - offset;
            }
        }
        if ((nullBits & 0x20) != 0x0) {
            final int fieldOffset6 = buf.getIntLE(offset + 22);
            int pos6 = offset + 30 + fieldOffset6;
            pos6 += InventorySection.computeBytesConsumed(buf, pos6);
            if (pos6 - offset > maxEnd) {
                maxEnd = pos6 - offset;
            }
        }
        if ((nullBits & 0x40) != 0x0) {
            final int fieldOffset7 = buf.getIntLE(offset + 26);
            int pos7 = offset + 30 + fieldOffset7;
            pos7 += InventorySection.computeBytesConsumed(buf, pos7);
            if (pos7 - offset > maxEnd) {
                maxEnd = pos7 - offset;
            }
        }
        return maxEnd;
    }
    
    @Override
    public void serialize(@Nonnull final ByteBuf buf) {
        final int startPos = buf.writerIndex();
        byte nullBits = 0;
        if (this.storage != null) {
            nullBits |= 0x1;
        }
        if (this.armor != null) {
            nullBits |= 0x2;
        }
        if (this.hotbar != null) {
            nullBits |= 0x4;
        }
        if (this.utility != null) {
            nullBits |= 0x8;
        }
        if (this.builderMaterial != null) {
            nullBits |= 0x10;
        }
        if (this.tools != null) {
            nullBits |= 0x20;
        }
        if (this.backpack != null) {
            nullBits |= 0x40;
        }
        buf.writeByte(nullBits);
        buf.writeByte(this.sortType.getValue());
        final int storageOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int armorOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int hotbarOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int utilityOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int builderMaterialOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int toolsOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int backpackOffsetSlot = buf.writerIndex();
        buf.writeIntLE(0);
        final int varBlockStart = buf.writerIndex();
        if (this.storage != null) {
            buf.setIntLE(storageOffsetSlot, buf.writerIndex() - varBlockStart);
            this.storage.serialize(buf);
        }
        else {
            buf.setIntLE(storageOffsetSlot, -1);
        }
        if (this.armor != null) {
            buf.setIntLE(armorOffsetSlot, buf.writerIndex() - varBlockStart);
            this.armor.serialize(buf);
        }
        else {
            buf.setIntLE(armorOffsetSlot, -1);
        }
        if (this.hotbar != null) {
            buf.setIntLE(hotbarOffsetSlot, buf.writerIndex() - varBlockStart);
            this.hotbar.serialize(buf);
        }
        else {
            buf.setIntLE(hotbarOffsetSlot, -1);
        }
        if (this.utility != null) {
            buf.setIntLE(utilityOffsetSlot, buf.writerIndex() - varBlockStart);
            this.utility.serialize(buf);
        }
        else {
            buf.setIntLE(utilityOffsetSlot, -1);
        }
        if (this.builderMaterial != null) {
            buf.setIntLE(builderMaterialOffsetSlot, buf.writerIndex() - varBlockStart);
            this.builderMaterial.serialize(buf);
        }
        else {
            buf.setIntLE(builderMaterialOffsetSlot, -1);
        }
        if (this.tools != null) {
            buf.setIntLE(toolsOffsetSlot, buf.writerIndex() - varBlockStart);
            this.tools.serialize(buf);
        }
        else {
            buf.setIntLE(toolsOffsetSlot, -1);
        }
        if (this.backpack != null) {
            buf.setIntLE(backpackOffsetSlot, buf.writerIndex() - varBlockStart);
            this.backpack.serialize(buf);
        }
        else {
            buf.setIntLE(backpackOffsetSlot, -1);
        }
    }
    
    @Override
    public int computeSize() {
        int size = 30;
        if (this.storage != null) {
            size += this.storage.computeSize();
        }
        if (this.armor != null) {
            size += this.armor.computeSize();
        }
        if (this.hotbar != null) {
            size += this.hotbar.computeSize();
        }
        if (this.utility != null) {
            size += this.utility.computeSize();
        }
        if (this.builderMaterial != null) {
            size += this.builderMaterial.computeSize();
        }
        if (this.tools != null) {
            size += this.tools.computeSize();
        }
        if (this.backpack != null) {
            size += this.backpack.computeSize();
        }
        return size;
    }
    
    public static ValidationResult validateStructure(@Nonnull final ByteBuf buffer, final int offset) {
        if (buffer.readableBytes() - offset < 30) {
            return ValidationResult.error("Buffer too small: expected at least 30 bytes");
        }
        final byte nullBits = buffer.getByte(offset);
        if ((nullBits & 0x1) != 0x0) {
            final int storageOffset = buffer.getIntLE(offset + 2);
            if (storageOffset < 0) {
                return ValidationResult.error("Invalid offset for Storage");
            }
            int pos = offset + 30 + storageOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for Storage");
            }
            final ValidationResult storageResult = InventorySection.validateStructure(buffer, pos);
            if (!storageResult.isValid()) {
                return ValidationResult.error("Invalid Storage: " + storageResult.error());
            }
            pos += InventorySection.computeBytesConsumed(buffer, pos);
        }
        if ((nullBits & 0x2) != 0x0) {
            final int armorOffset = buffer.getIntLE(offset + 6);
            if (armorOffset < 0) {
                return ValidationResult.error("Invalid offset for Armor");
            }
            int pos = offset + 30 + armorOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for Armor");
            }
            final ValidationResult armorResult = InventorySection.validateStructure(buffer, pos);
            if (!armorResult.isValid()) {
                return ValidationResult.error("Invalid Armor: " + armorResult.error());
            }
            pos += InventorySection.computeBytesConsumed(buffer, pos);
        }
        if ((nullBits & 0x4) != 0x0) {
            final int hotbarOffset = buffer.getIntLE(offset + 10);
            if (hotbarOffset < 0) {
                return ValidationResult.error("Invalid offset for Hotbar");
            }
            int pos = offset + 30 + hotbarOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for Hotbar");
            }
            final ValidationResult hotbarResult = InventorySection.validateStructure(buffer, pos);
            if (!hotbarResult.isValid()) {
                return ValidationResult.error("Invalid Hotbar: " + hotbarResult.error());
            }
            pos += InventorySection.computeBytesConsumed(buffer, pos);
        }
        if ((nullBits & 0x8) != 0x0) {
            final int utilityOffset = buffer.getIntLE(offset + 14);
            if (utilityOffset < 0) {
                return ValidationResult.error("Invalid offset for Utility");
            }
            int pos = offset + 30 + utilityOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for Utility");
            }
            final ValidationResult utilityResult = InventorySection.validateStructure(buffer, pos);
            if (!utilityResult.isValid()) {
                return ValidationResult.error("Invalid Utility: " + utilityResult.error());
            }
            pos += InventorySection.computeBytesConsumed(buffer, pos);
        }
        if ((nullBits & 0x10) != 0x0) {
            final int builderMaterialOffset = buffer.getIntLE(offset + 18);
            if (builderMaterialOffset < 0) {
                return ValidationResult.error("Invalid offset for BuilderMaterial");
            }
            int pos = offset + 30 + builderMaterialOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for BuilderMaterial");
            }
            final ValidationResult builderMaterialResult = InventorySection.validateStructure(buffer, pos);
            if (!builderMaterialResult.isValid()) {
                return ValidationResult.error("Invalid BuilderMaterial: " + builderMaterialResult.error());
            }
            pos += InventorySection.computeBytesConsumed(buffer, pos);
        }
        if ((nullBits & 0x20) != 0x0) {
            final int toolsOffset = buffer.getIntLE(offset + 22);
            if (toolsOffset < 0) {
                return ValidationResult.error("Invalid offset for Tools");
            }
            int pos = offset + 30 + toolsOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for Tools");
            }
            final ValidationResult toolsResult = InventorySection.validateStructure(buffer, pos);
            if (!toolsResult.isValid()) {
                return ValidationResult.error("Invalid Tools: " + toolsResult.error());
            }
            pos += InventorySection.computeBytesConsumed(buffer, pos);
        }
        if ((nullBits & 0x40) != 0x0) {
            final int backpackOffset = buffer.getIntLE(offset + 26);
            if (backpackOffset < 0) {
                return ValidationResult.error("Invalid offset for Backpack");
            }
            int pos = offset + 30 + backpackOffset;
            if (pos >= buffer.writerIndex()) {
                return ValidationResult.error("Offset out of bounds for Backpack");
            }
            final ValidationResult backpackResult = InventorySection.validateStructure(buffer, pos);
            if (!backpackResult.isValid()) {
                return ValidationResult.error("Invalid Backpack: " + backpackResult.error());
            }
            pos += InventorySection.computeBytesConsumed(buffer, pos);
        }
        return ValidationResult.OK;
    }
    
    public UpdatePlayerInventory clone() {
        final UpdatePlayerInventory copy = new UpdatePlayerInventory();
        copy.storage = ((this.storage != null) ? this.storage.clone() : null);
        copy.armor = ((this.armor != null) ? this.armor.clone() : null);
        copy.hotbar = ((this.hotbar != null) ? this.hotbar.clone() : null);
        copy.utility = ((this.utility != null) ? this.utility.clone() : null);
        copy.builderMaterial = ((this.builderMaterial != null) ? this.builderMaterial.clone() : null);
        copy.tools = ((this.tools != null) ? this.tools.clone() : null);
        copy.backpack = ((this.backpack != null) ? this.backpack.clone() : null);
        copy.sortType = this.sortType;
        return copy;
    }
    
    @Override
    public boolean equals(final Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj instanceof final UpdatePlayerInventory other) {
            return Objects.equals(this.storage, other.storage) && Objects.equals(this.armor, other.armor) && Objects.equals(this.hotbar, other.hotbar) && Objects.equals(this.utility, other.utility) && Objects.equals(this.builderMaterial, other.builderMaterial) && Objects.equals(this.tools, other.tools) && Objects.equals(this.backpack, other.backpack) && Objects.equals(this.sortType, other.sortType);
        }
        return false;
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(this.storage, this.armor, this.hotbar, this.utility, this.builderMaterial, this.tools, this.backpack, this.sortType);
    }
}
