package de.dhbwstuttgart.syntaxtree;

import java.util.ArrayList;
import java.util.Objects;

import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation;
import de.dhbwstuttgart.typeinference.typeAlgo.TYPE;
import de.dhbwstuttgart.typeinference.typeAlgo.TYPEStmt;
import org.antlr.v4.runtime.Token;

import de.dhbwstuttgart.core.IItemWithOffset;
import de.dhbwstuttgart.syntaxtree.statement.Block;

/**
 * Stellt eine Methode dar. Problem: Parser kann nicht zwischen Methode und
 * Konstruktor unterscheiden. Daher kann diese Klasse beides sein. Dies wird mit
 * dem ParserPostProcessing behoben.
 * 
 * @author janulrich
 *
 */
public class Method extends SyntaxTreeNode implements IItemWithOffset, TypeScope
{
	public final Block block;
	public final int modifier;
	public final String name;
	private ParameterList parameterlist = new ParameterList(new ArrayList<>(), new NullToken());
	private ExceptionList exceptionlist;
	private GenericDeclarationList generics;
	private final RefTypeOrTPHOrWildcardOrGeneric returnType;
	public final Boolean isInherited; 
	public final Boolean isImplemented;
	
	/*
	 * its Constraints
	 * eingefuegt PL 2021-02-15
	 */
	public final ConstraintSet constraints = new ConstraintSet();
	
	public Method(int modifier, String name, RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList parameterList, Block block,
				  GenericDeclarationList gtvDeclarations, Token offset) {
		super(offset);
		this.name = name;
		this.modifier = modifier;
		this.returnType = returnType;
		this.parameterlist = parameterList;
		this.block = block;
		this.generics = gtvDeclarations;
		this.isInherited = false;
		this.isImplemented = false;
	}
	
	public Method(int modifier, String name, RefTypeOrTPHOrWildcardOrGeneric returnType, ParameterList parameterList, Block block,
			  GenericDeclarationList gtvDeclarations, Token offset, Boolean isInherited, Boolean isOverridden) {
		super(offset);
		this.name = name;
		this.modifier = modifier;
		this.returnType = returnType;
		this.parameterlist = parameterList;
		this.block = block;
		this.generics = gtvDeclarations;
		this.isInherited = isInherited;
		this.isImplemented = isOverridden;
	}

	public ParameterList getParameterList() {
		return parameterlist;
	}

	public GenericDeclarationList getGenerics() {
		return generics;
	}

	@Override
	public RefTypeOrTPHOrWildcardOrGeneric getReturnType() {
		return this.returnType;
	}

	public ConstraintSet getConstraints() {
		return this.constraints;
	}
	
	@Override
	public void accept(ASTVisitor visitor) {
		visitor.visit(this);
	}

	@Override
	public Token getOffset() {
		return super.getOffset();
	}

	public String getName() {
		return name;
	}

	@Override
	public boolean equals(Object o) {
		if (this == o) return true;
		if (o == null || getClass() != o.getClass()) return false;
		Method method = (Method) o;
		return Objects.equals(name, method.name) && Objects.equals(parameterlist, method.parameterlist) && Objects.equals(returnType, method.returnType);
	}

	@Override
	public int hashCode() {
		return Objects.hash(name, parameterlist, returnType);
	}
	
	@Override
	public String toString() {
		return name;
	
	}
}
