/*
 * Decompiled with CFR 0.152.
 */
package com.evilco.mc.nbt.tag;

import com.evilco.mc.nbt.error.TagNotFoundException;
import com.evilco.mc.nbt.error.UnexpectedTagTypeException;
import com.evilco.mc.nbt.stream.NbtInputStream;
import com.evilco.mc.nbt.stream.NbtOutputStream;
import com.evilco.mc.nbt.tag.AbstractTag;
import com.evilco.mc.nbt.tag.INamedTagContainer;
import com.evilco.mc.nbt.tag.ITag;
import com.evilco.mc.nbt.tag.TagByte;
import com.evilco.mc.nbt.tag.TagByteArray;
import com.evilco.mc.nbt.tag.TagDouble;
import com.evilco.mc.nbt.tag.TagFloat;
import com.evilco.mc.nbt.tag.TagInteger;
import com.evilco.mc.nbt.tag.TagIntegerArray;
import com.evilco.mc.nbt.tag.TagList;
import com.evilco.mc.nbt.tag.TagLong;
import com.evilco.mc.nbt.tag.TagShort;
import com.evilco.mc.nbt.tag.TagString;
import com.evilco.mc.nbt.tag.TagType;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Nonnull;

public class TagCompound
extends AbstractTag
implements INamedTagContainer {
    protected Map<String, ITag> tags = new HashMap<String, ITag>();

    public TagCompound(String name) {
        super(name);
    }

    public TagCompound(@Nonnull NbtInputStream inputStream, boolean anonymous) throws IOException {
        super(inputStream, anonymous);
        while (true) {
            byte type;
            TagType tagType;
            if ((tagType = TagType.valueOf(type = inputStream.readByte())) == null) {
                throw new IOException("Could not find a tag for type ID " + type + ".");
            }
            if (tagType == TagType.END) break;
            this.setTag(inputStream.readTag(tagType, false));
        }
    }

    @Override
    public ITag getTag(@Nonnull String name) {
        Preconditions.checkNotNull(name, "name");
        return this.tags.get(name);
    }

    @Override
    public <T extends ITag> T getTag(String name, Class<T> tagClass) throws UnexpectedTagTypeException, TagNotFoundException {
        ITag tag = this.getTag(name);
        if (tag == null) {
            throw new TagNotFoundException("The compound tag is missing a " + name + " entry");
        }
        if (!tagClass.isInstance(tag)) {
            throw new UnexpectedTagTypeException("The compound entry " + name + " should be of type " + tagClass.getSimpleName() + ", but is of type " + tag.getClass().getSimpleName());
        }
        return (T)tag;
    }

    public TagCompound getCompound(String name) throws UnexpectedTagTypeException, TagNotFoundException {
        return this.getTag(name, TagCompound.class);
    }

    public int getInteger(String name) throws UnexpectedTagTypeException, TagNotFoundException {
        return this.getTag(name, TagInteger.class).getValue();
    }

    public short getShort(String name) throws UnexpectedTagTypeException, TagNotFoundException {
        return this.getTag(name, TagShort.class).getValue();
    }

    public byte getByte(String name) throws UnexpectedTagTypeException, TagNotFoundException {
        return this.getTag(name, TagByte.class).getValue();
    }

    public long getLong(String name) throws UnexpectedTagTypeException, TagNotFoundException {
        return this.getTag(name, TagLong.class).getValue();
    }

    public double getDouble(String name) throws UnexpectedTagTypeException, TagNotFoundException {
        return this.getTag(name, TagDouble.class).getValue();
    }

    public float getFloat(String name) throws UnexpectedTagTypeException, TagNotFoundException {
        return this.getTag(name, TagFloat.class).getValue();
    }

    public String getString(String name) throws UnexpectedTagTypeException, TagNotFoundException {
        return this.getTag(name, TagString.class).getValue();
    }

    public <T extends ITag> List<T> getList(String name, Class<T> itemClass) throws UnexpectedTagTypeException, TagNotFoundException {
        return this.getTag(name, TagList.class).getTags(itemClass);
    }

    public int[] getIntegerArray(String name) throws UnexpectedTagTypeException, TagNotFoundException {
        return this.getTag(name, TagIntegerArray.class).getValues();
    }

    public byte[] getByteArray(String name) throws UnexpectedTagTypeException, TagNotFoundException {
        return this.getTag(name, TagByteArray.class).getValue();
    }

    public String[] getStringArray(String name) throws UnexpectedTagTypeException, TagNotFoundException {
        List<TagString> tags = this.getList(name, TagString.class);
        String[] array = new String[tags.size()];
        for (int i = 0; i < tags.size(); ++i) {
            array[i] = tags.get(i).getValue();
        }
        return array;
    }

    public double[] getDoubleArray(String name) throws UnexpectedTagTypeException, TagNotFoundException {
        List<TagDouble> tags = this.getList(name, TagDouble.class);
        double[] array = new double[tags.size()];
        for (int i = 0; i < tags.size(); ++i) {
            array[i] = tags.get(i).getValue();
        }
        return array;
    }

    public float[] getFloatArray(String name) throws UnexpectedTagTypeException, TagNotFoundException {
        List<TagFloat> tags = this.getList(name, TagFloat.class);
        float[] array = new float[tags.size()];
        for (int i = 0; i < tags.size(); ++i) {
            array[i] = tags.get(i).getValue();
        }
        return array;
    }

    @Override
    public Map<String, ITag> getTags() {
        return new ImmutableMap.Builder<String, ITag>().putAll(this.tags).build();
    }

    @Override
    public void removeTag(@Nonnull ITag tag) {
        Preconditions.checkNotNull(tag, "tag");
        this.tags.remove(tag.getName());
    }

    @Override
    public void removeTag(@Nonnull String tag) {
        Preconditions.checkNotNull(tag, "tag");
        this.tags.remove(tag);
    }

    @Override
    public void setTag(@Nonnull ITag tag) {
        Preconditions.checkNotNull(tag, "tag");
        if (this.tags.containsKey(tag)) {
            this.tags.get(tag.getName()).setParent(null);
        }
        this.tags.put(tag.getName(), tag);
        tag.setParent(this);
    }

    @Override
    public byte getTagID() {
        return TagType.COMPOUND.typeID;
    }

    @Override
    public void write(NbtOutputStream outputStream, boolean anonymous) throws IOException {
        super.write(outputStream, anonymous);
        for (Map.Entry<String, ITag> tagEntry : this.tags.entrySet()) {
            outputStream.writeByte(tagEntry.getValue().getTagID());
            tagEntry.getValue().write(outputStream, false);
        }
        outputStream.writeByte(TagType.END.typeID);
    }
}
