package de.dhbwstuttgart.typeinference.constraints;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.unify.model.PairOperator;


public class Pair implements Serializable
{
    public final RefTypeOrTPHOrWildcardOrGeneric TA1;
    public final RefTypeOrTPHOrWildcardOrGeneric TA2;

    private PairOperator eOperator = PairOperator.SMALLER;
    

    public Pair(RefTypeOrTPHOrWildcardOrGeneric TA1, RefTypeOrTPHOrWildcardOrGeneric TA2 )
    {
        this.TA1 = TA1;
        this.TA2 = TA2;
        if(TA1 == null || TA2 == null)
            throw new NullPointerException();
        eOperator = PairOperator.SMALLER;
    }

    public Pair(RefTypeOrTPHOrWildcardOrGeneric TA1, RefTypeOrTPHOrWildcardOrGeneric TA2, PairOperator eOp)
    {
        // Konstruktor
        this(TA1,TA2);
        this.eOperator = eOp;
    }

    public String toString()
    {
        // otth: Gibt ein Paar als String aus --> zum Debuggen und Vergleichen
        String strElement1 = "NULL";
        String strElement2 = "NULL";
        String Operator = "<.";
        
        if( TA1 != null )
             strElement1 = TA1.toString();
    
        if( TA2 != null )
           strElement2 = TA2.toString();
        
       /* PL ausskommentiert 2018-05-24
        if(OperatorEqual())
        	Operator = "=";
        if(OperatorSmaller())
        	Operator = "<.";
        if(OperatorSmallerExtends())
        	Operator = "<?";
        	*/
        
        return "\n(" + strElement1 + " " + eOperator.toString() + " " + strElement2 + ")";
        
       /*- Equals: " + bEqual*/
    }

    /**
     * <br/>Author: JÃ¯Â¿Â½rg BÃ¯Â¿Â½uerle
     * @param obj
     * @return
     */
    public boolean equals(Object obj)
    {
        boolean ret = true;
        ret &= (obj instanceof Pair);
        if(!ret)return ret;
        ret &= ((Pair)obj).TA1.equals(this.TA1);
        ret &= ((Pair)obj).TA2.equals(this.TA2);
        return ret;
    }

    /**
	* Author: Arne LÃ¼dtke<br/>
	* Abfrage, ob Operator vom Typ Equal ist.
	*/
    public boolean OperatorEqual()
    {
    	return eOperator == PairOperator.EQUALSDOT;
    }
    
    /**
	* Author: Arne LÃ¼dtke<br/>
	* Abfrage, ob Operator vom Typ Smaller ist.
	*/
    public boolean OperatorSmaller()
    {
    	return eOperator == PairOperator.SMALLER;
    }
    
    /**
	* Author: Arne LÃ¼dtke<br/>
	* Abfrage, ob Operator vom Typ SmallerExtends ist.
	*/
    public boolean OperatorSmallerExtends()
    {
    	return eOperator == PairOperator.SMALLERDOTWC;
    }
    
    /**
	* Author: Arne LÃ¼dtke<br/>
	* Gibt den Operator zurÃ¼ck.
	*/
    public PairOperator GetOperator()
    {
    	return eOperator;
    }

    public boolean OperatorSmallerDot() {
        return eOperator == PairOperator.SMALLERDOT;
    }
    
    
    static public Map<String, TypePlaceholder> generateTPHMap(ConstraintSet<Pair> constraints) {
        HashMap<String, TypePlaceholder> ret = new HashMap<>();
        constraints.map((Pair p) -> {
            if (p.TA1 instanceof TypePlaceholder) {
                ret.put(((TypePlaceholder) p.TA1).getName(), (TypePlaceholder) p.TA1);
            }
            if (p.TA2 instanceof TypePlaceholder) {
                ret.put(((TypePlaceholder) p.TA2).getName(), (TypePlaceholder) p.TA2);
            }
            return null;
        });
        return ret;
    }
}
// ino.end
