package me.tomassetti.turin.definitions;

import me.tomassetti.jvm.JvmConstructorDefinition;
import me.tomassetti.jvm.JvmMethodDefinition;
import me.tomassetti.jvm.JvmType;
import me.tomassetti.turin.parser.analysis.resolvers.SymbolResolver;
import me.tomassetti.turin.parser.ast.Named;
import me.tomassetti.turin.parser.ast.Node;
import me.tomassetti.turin.parser.ast.QualifiedName;
import me.tomassetti.turin.parser.ast.expressions.ActualParam;
import me.tomassetti.turin.symbols.FormalParameter;
import me.tomassetti.turin.symbols.Symbol;
import me.tomassetti.turin.typesystem.ReferenceTypeUsage;
import me.tomassetti.turin.typesystem.TypeUsage;

import java.util.List;
import java.util.Map;
import java.util.Optional;

public interface TypeDefinition extends Symbol, Named {

    String getQualifiedName();

    JvmType jvmType();

    JvmConstructorDefinition resolveConstructorCall(SymbolResolver resolver, List<ActualParam> actualParams);

    boolean hasManyConstructors(SymbolResolver resolver);

    List<? extends FormalParameter> getConstructorParams(List<ActualParam> actualParams, SymbolResolver resolver);

    Optional<JvmConstructorDefinition> findConstructorDefinition(List<ActualParam> actualParams, SymbolResolver resolver);

    Optional<InternalConstructorDefinition> findConstructor(List<ActualParam> actualParams, SymbolResolver resolver);

    InternalConstructorDefinition getConstructor(List<ActualParam> actualParams, SymbolResolver resolver);

    List<InternalConstructorDefinition> getConstructors(SymbolResolver resolver);

    JvmMethodDefinition findMethodFor(String name, List<JvmType> argsTypes, SymbolResolver resolver, boolean staticContext);

    boolean isMethodOverloaded(String methodName, SymbolResolver resolver);

    Optional<InternalMethodDefinition> findMethod(String methodName, List<ActualParam> actualParams, SymbolResolver resolver, boolean staticContext);

    TypeUsage returnTypeWhenInvokedWith(String methodName, List<ActualParam> actualParams, SymbolResolver resolver, boolean staticContext);

    List<? extends FormalParameter> getMethodParams(String methodName, List<ActualParam> actualParams, SymbolResolver resolver, boolean staticContext);

    boolean hasMethodFor(String methodName, List<ActualParam> actualParams, SymbolResolver resolver, boolean staticContext);

    InternalMethodDefinition getMethod(String methodName, List<ActualParam> actualParams, SymbolResolver resolver, boolean staticContext);

    TypeUsage getFieldType(String fieldName, boolean staticContext, SymbolResolver resolver);

    Node getFieldOnInstance(String fieldName, Node instance, SymbolResolver resolver);

    boolean hasField(String name, boolean staticContext);

    boolean hasField(QualifiedName fieldName, boolean staticContext, SymbolResolver resolver);

    boolean canFieldBeAssigned(String field, SymbolResolver resolver);

    List<ReferenceTypeUsage> getAllAncestors(SymbolResolver resolver);

    boolean isInterface();

    boolean isClass();

    TypeDefinition getSuperclass(SymbolResolver resolver);

    <T extends TypeUsage> Map<String, TypeUsage> associatedTypeParametersToName(SymbolResolver resolver, List<T> typeParams);
}

@@ -781,58 +781,819 @@
     
-String getQualifiedName();%0A%0A    JvmType jvmType();
+///%0A    /// Naming%0A    ///%0A%0A    String getQualifiedName();%0A%0A    ///%0A    /// Hierarchy%0A    ///%0A%0A    List%3CReferenceTypeUsage%3E getAllAncestors(SymbolResolver resolver);%0A%0A    TypeDefinition getSuperclass(SymbolResolver resolver);%0A%0A    ///%0A    /// Type%0A    ///%0A%0A    boolean isInterface();%0A%0A    boolean isClass();%0A%0A    JvmType jvmType();%0A%0A    ///%0A    /// Fields%0A    ///%0A%0A    TypeUsage getFieldType(String fieldName, boolean staticContext, SymbolResolver resolver);%0A%0A    Node getFieldOnInstance(String fieldName, Node instance, SymbolResolver resolver);%0A%0A    boolean hasField(String name, boolean staticContext);%0A%0A    boolean hasField(QualifiedName fieldName, boolean staticContext, SymbolResolver resolver);%0A%0A    boolean canFieldBeAssigned(String field, SymbolResolver resolver);%0A%0A    ///%0A    /// Constructors%0A    ///
 %0A%0A  
@@ -2306,24 +2306,57 @@
 resolver);%0A%0A
+    ///%0A    /// Methods%0A    ///%0A%0A
     JvmMetho
@@ -3265,596 +3265,32 @@
     
-TypeUsage getFieldType(String fieldName, boolean staticContext, SymbolResolver resolver);%0A%0A    Node getFieldOnInstance(String fieldName, Node instance, SymbolResolver resolver);%0A%0A    boolean hasField(String name, boolean staticContext);%0A%0A    boolean hasField(QualifiedName fieldName, boolean staticContext, SymbolResolver resolver);%0A%0A    boolean canFieldBeAssigned(String field, SymbolResolver resolver);%0A%0A    List%3CReferenceTypeUsage%3E getAllAncestors(SymbolResolver resolver);%0A%0A    boolean isInterface();%0A%0A    boolean isClass();%0A%0A    TypeDefinition getSuperclass(SymbolResolver resolver);
+///%0A    /// Misc%0A    ///
 %0A%0A  

reorganize TypeDefinition