package net.minecraft.command.type.management;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.commons.collections4.trie.PatriciaTrie;
import net.minecraft.command.CommandException;
import net.minecraft.command.ParsingUtilities;
import net.minecraft.command.SyntaxErrorException;
import net.minecraft.command.arg.ArgWrapper;
import net.minecraft.command.arg.CommandArg;
import net.minecraft.command.arg.PrimitiveParameter;
import net.minecraft.command.collections.Relations;
import net.minecraft.command.completion.TabCompletion;
import net.minecraft.command.parser.Context;
import net.minecraft.command.parser.Parser;
import net.minecraft.command.type.CDataType;
import net.minecraft.command.type.CTypeParse;
import net.minecraft.command.type.IParse;
import net.minecraft.command.type.custom.TypeTypeID;
public class TypeID<T> extends CConvertable<CommandArg<T>, ArgWrapper<T>>
{
private static final PatriciaTrie<TypeID<?>> typeIDs = new PatriciaTrie<>();
public final Convertable<T, ?, CommandException> primitive;
public final TabCompletion completion;
public final IParse<TypeID<?>> typeIDParser;
public TypeID(final String name)
{
super(name);
if (ParsingUtilities.spaceMatcher.matcher(name).matches() || !ParsingUtilities.stringMatcher.matcher(name).matches())
throw new IllegalArgumentException("Invalid name for TypeID: '" + name + "'");
this.typeIDParser = new TypeTypeID(Collections.<TypeID<?>> singleton(this));
this.primitive = new ConvertableUnwrapped<>(name + ".primitive");
this.completion = new TabCompletion.Escaped(name);
}
@Override
public void init()
{
typeIDs.put(this.name, this);
this.primitive.init();
super.init();
Relations.commandArg.registerPair(this.primitive, this);
}
public static TypeID<?> get(final String name)
{
return typeIDs.get(name);
}
public static void clearAll()
{
typeIDs.clear();
}
// checked...
@SuppressWarnings("unchecked")
@Override
public ArgWrapper<T> convertFrom(final Parser parser, final ArgWrapper<?> toConvert) throws SyntaxErrorException
{
if (toConvert.type == this)
return (ArgWrapper<T>) toConvert;
return this.wrap(toConvert.iConvertTo(parser, this));
}
public ArgWrapper<T> wrap(final CommandArg<T> toWrap)
{
return toWrap.wrap(this);
}
public ArgWrapper<T> wrap(final T toWrap)
{
return new PrimitiveParameter<>(toWrap).wrap(this);
}
public CDataType<T> wrap(final IParse<? extends CommandArg<T>> toWrap)
{
return new CTypeParse<T>()
{
@Override
public ArgWrapper<T> iParse(final Parser parser, final Context context) throws SyntaxErrorException
{
return TypeID.this.wrap(toWrap.parse(parser, context));
}
};
}
public final <U> void addPrimitiveConverter(final TypeID<U> type, final Converter<T, U, ?> converter)
{
this.primitive.addConverter(type.primitive, converter);
}
public static interface ExceptionProvider
{
public CommandException create();
}
public final TypeID<List<T>> addList(final ExceptionProvider provider, final String listName)
{
final TypeID<List<T>> list = new TypeID<List<T>>(listName)
{
@Override
public void init()
{
super.init();
Relations.list.registerPair(TypeID.this.primitive, this.primitive);
Relations.relDefault.registerPair(this.primitive, TypeID.this.primitive, new Converter<List<T>, T, CommandException>()
{
@Override
public final T convert(final List<T> toConvert) throws CommandException
{
if (toConvert.size() != 1)
throw provider.create();
return toConvert.get(0);
}
});
Relations.relDefault.registerPair(TypeID.this.primitive, this.primitive, new Converter<T, List<T>, SyntaxErrorException>()
{
@Override
public List<T> convert(final T toConvert)
{
final List<T> list = new ArrayList<>();
list.add(toConvert);
return list;
}
});
}
};
return list;
}
public final TypeID<List<T>> addList(final ExceptionProvider provider)
{
return this.addList(provider, this.name + ".list");
}
public final TypeID<List<T>> addList(final String listName)
{
return this.addList(this.listToItemProvider(), listName);
}
public final TypeID<List<T>> addList()
{
return this.addList(this.name + ".list");
}
public final ExceptionProvider listToItemProvider()
{
return new ExceptionProvider()
{
@Override
public CommandException create()
{
return new CommandException("The " + TypeID.this.name + "-list does not contain a single element");
}
};
}
public final <R> void addDefaultConverter(final TypeID<R> target, final Converter<T, R, ?> converter)
{
Relations.relDefault.registerPair(this.primitive, target.primitive, converter);
}
public final <R> void addChild(final TypeID<R> child, final Converter<R, T, ?> converter)
{
child.addDefaultConverter(this, converter);
Relations.relSuper.registerPair(this.primitive, child.primitive, converter);
}
}