package me.tomassetti.turin.implicit;

import com.google.common.collect.ImmutableList;
import me.tomassetti.jvm.JvmType;
import me.tomassetti.turin.parser.analysis.resolvers.SymbolResolver;
import me.tomassetti.turin.parser.ast.Node;
import me.tomassetti.turin.parser.ast.typeusage.PrimitiveTypeUsage;
import me.tomassetti.turin.parser.ast.typeusage.TypeUsage;

import java.util.Collections;
import java.util.Optional;

/**
 * NOTE: Being a Node we could need to have separate instances for each occurrence, so that each one can have a proper
 *       parent.
 */
public class BasicTypeUsage extends TypeUsage {

    public static BasicTypeUsage UINT = new BasicTypeUsage("uint", PrimitiveTypeUsage.INT);

    private static ImmutableList<BasicTypeUsage> BASIC_TYPES = ImmutableList.of(UINT);

    private String name;
    private PrimitiveTypeUsage correspondingPrimitiveTypeUsage;

    private BasicTypeUsage(String name, PrimitiveTypeUsage correspondingPrimitiveTypeUsage) {
        this.name = name;
        this.correspondingPrimitiveTypeUsage = correspondingPrimitiveTypeUsage;
    }

    @Override
    public boolean isPrimitive() {
        return true;
    }

    @Override
    public PrimitiveTypeUsage asPrimitiveTypeUsage() {
        return correspondingPrimitiveTypeUsage;
    }

    @Override
    public boolean isMethodOverloaded(SymbolResolver resolver, String methodName) {
        return false;
    }

    @Override
    public JvmType jvmType(SymbolResolver resolver) {
        return correspondingPrimitiveTypeUsage.jvmType(resolver);
    }

    @Override
    public Iterable<Node> getChildren() {
        return Collections.emptyList();
    }

    @Override
    public String toString() {
        return "BasicTypeUsage{" +
                "name='" + name + '\'' +
                ", correspondingPrimitiveTypeUsage=" + correspondingPrimitiveTypeUsage +
                '}';
    }

    public static Optional<BasicTypeUsage> findByName(String typeName) {
        for (BasicTypeUsage basicTypeUsage : BASIC_TYPES) {
            if (basicTypeUsage.name.equals(typeName)) {
                return Optional.of(basicTypeUsage);
            }
        }
        return Optional.empty();
    }

    public static BasicTypeUsage getByName(String typeName) {
        for (BasicTypeUsage basicTypeUsage : BASIC_TYPES) {
            if (basicTypeUsage.name.equals(typeName)) {
                return basicTypeUsage;
            }
        }
        throw new IllegalArgumentException(typeName);
    }

}

@@ -644,63 +644,550 @@
 ge U
-INT = new BasicTypeUsage(%22uint%22, PrimitiveTypeUsage.INT
+BYTE = new BasicTypeUsage(%22ubyte%22, PrimitiveTypeUsage.BYTE);%0A    public static BasicTypeUsage USHORT = new BasicTypeUsage(%22ushort%22, PrimitiveTypeUsage.SHORT);%0A    public static BasicTypeUsage UINT = new BasicTypeUsage(%22uint%22, PrimitiveTypeUsage.INT);%0A    public static BasicTypeUsage ULONG = new BasicTypeUsage(%22ulong%22, PrimitiveTypeUsage.LONG);%0A    public static BasicTypeUsage UFLOAT = new BasicTypeUsage(%22ufloat%22, PrimitiveTypeUsage.FLOAT);%0A    public static BasicTypeUsage UDOUBLE = new BasicTypeUsage(%22udouble%22, PrimitiveTypeUsage.DOUBLE
 );%0A%0A
@@ -1267,19 +1267,58 @@
 ist.of(U
-INT
+BYTE, USHORT, UINT, ULONG, UFLOAT, UDOUBLE
 );%0A%0A    

complete basic types