package com.cricketcraft.chisel.carving;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import net.minecraft.block.Block;
import org.apache.commons.lang3.tuple.Pair;
import com.cricketcraft.chisel.api.carving.ICarvingGroup;
import com.cricketcraft.chisel.api.carving.ICarvingVariation;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
public class GroupList implements Set<ICarvingGroup> {
private class VariationWrapper {
private ICarvingVariation v;
private VariationWrapper(ICarvingVariation v) {
this.v = v;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof ICarvingVariation) {
ICarvingVariation v2 = (ICarvingVariation) obj;
return v.getBlock() == v2.getBlock() && (v.getBlockMeta() == v2.getBlockMeta() || v.getItemMeta() == v2.getItemMeta());
} else if (obj instanceof VariationWrapper) {
return equals(((VariationWrapper) obj).v);
}
return false;
}
@Override
public int hashCode() {
return v.getBlock().hashCode();
}
}
private class VariationKey implements ICarvingVariation {
Pair<Block, Integer> data;
private VariationKey(Block block, int blockMeta) {
data = Pair.of(block, blockMeta);
}
@Override
public Block getBlock() {
return data.getLeft();
}
@Override
public int getBlockMeta() {
return data.getRight();
}
@Override
public int getItemMeta() {
return data.getRight();
}
@Override
public int getOrder() {
return 0;
}
@Override
public String toString() {
return data.toString();
}
}
private HashMap<String, ICarvingGroup> groups = Maps.newHashMap();
private HashMap<VariationWrapper, ICarvingGroup> lookup = Maps.newHashMap();
@Override
public int size() {
return groups.size();
}
@Override
public boolean isEmpty() {
return groups.isEmpty();
}
@Override
public boolean contains(Object o) {
if (o instanceof ICarvingGroup) {
return groups.containsKey(((ICarvingGroup) o).getName());
}
return false;
}
@Override
public Iterator<ICarvingGroup> iterator() {
return groups.values().iterator();
}
@Override
public Object[] toArray() {
return groups.values().toArray();
}
@Override
public <T> T[] toArray(T[] arr) {
return groups.values().toArray(arr);
}
@Override
public boolean add(ICarvingGroup group) {
String key = group.getName();
if (groups.containsKey(key)) {
return false;
}
for (ICarvingVariation v : group.getVariations()) {
ICarvingGroup g = lookup.get(v);
if (g == null) {
lookup.put(new VariationWrapper(v), group);
}
}
groups.put(key, group);
return true;
}
@Override
public boolean remove(Object o) {
if (o instanceof ICarvingGroup) {
List<VariationWrapper> toRemove = Lists.newArrayList();
for (VariationWrapper v : lookup.keySet()) {
if (lookup.get(v).getName().equals(((ICarvingGroup) o).getName())) {
toRemove.add(v);
}
}
for (VariationWrapper v : toRemove) {
lookup.remove(v);
}
return groups.remove(((ICarvingGroup) o).getName()) != null;
}
return false;
}
@Override
public boolean containsAll(Collection<?> c) {
for (Object o : c) {
if (!(o instanceof ICarvingGroup)) {
return false;
}
if (!groups.containsKey(((ICarvingGroup) o).getName())) {
return false;
}
}
return true;
}
@Override
public boolean addAll(Collection<? extends ICarvingGroup> c) {
boolean ret = false;
for (ICarvingGroup g : c) {
ret |= add(g);
}
return ret;
}
@Override
public boolean removeAll(Collection<?> c) {
boolean ret = false;
for (Object o : c) {
ret |= remove(o);
}
return ret;
}
@Override
public boolean retainAll(Collection<?> c) {
throw new UnsupportedOperationException(); // not using it, not gonna bother
}
@Override
public void clear() {
groups.clear();
}
public ICarvingGroup getGroup(Block block, int metadata) {
return lookup.get(new VariationWrapper(new VariationKey(block, metadata)));
}
public void addVariation(String name, ICarvingVariation variation) {
ICarvingGroup g = groups.get(name);
if (g == null) {
throw new NullPointerException("No group exists for name " + name);
}
g.addVariation(variation);
lookup.put(new VariationWrapper(variation), g);
}
public ICarvingGroup getGroupByName(String groupName) {
return groups.get(groupName);
}
public ICarvingGroup getGroupByOre(String oreName) {
for (ICarvingGroup group : groups.values()) {
if (oreName.equals(group.getOreName())) {
return group;
}
}
return null;
}
public Collection<? extends String> getNames() {
return groups.keySet();
}
public ICarvingVariation removeVariation(Block block, int metadata, String group) {
ICarvingGroup g = null;
if (group != null) {
g = groups.get(group);
if (g == null) {
throw new IllegalArgumentException("No such group " + group);
}
groups.remove(g.getName());
}
List<VariationWrapper> toRemove = Lists.newArrayList();
for (VariationWrapper v : lookup.keySet()) {
if ((g == null || lookup.get(v).getName().equals(g.getName())) && v.equals(new VariationWrapper(new VariationKey(block, metadata)))) {
lookup.get(v).removeVariation(v.v);
toRemove.add(v);
}
}
for (VariationWrapper v : toRemove) {
lookup.remove(v);
}
return toRemove.isEmpty() ? null : toRemove.get(0).v;
}
@Override
public String toString() {
return groups.toString();
}
}