package de.dhbwstuttgart.typeinference.unify;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import de.dhbwstuttgart.typeinference.unify.model.FunNType;
import de.dhbwstuttgart.typeinference.unify.model.PlaceholderType;
import de.dhbwstuttgart.typeinference.unify.model.TypeParams;
import de.dhbwstuttgart.typeinference.unify.model.UnifyType;

public class distributeVariance extends visitUnifyTypeVisitor<Integer> {
	
	public static int inverseVariance(int variance) { 
		Integer ret = 0;
		if (variance == 1) {
		   ret = -1;
		}
		if (variance == -1) {
			ret = 1;
		}
		return ret;
	}


	@Override
	public PlaceholderType visit(PlaceholderType phty, Integer ht) {
		if (ht != 0) {
			if (phty.getVariance() == 0) {
				phty.setVariance(ht);
			}
			//PL 2018-05-17 urspruengliche Variance nicht veraendern
			//else if (phty.getVariance() != ht) {
			//	phty.setVariance(0);
			//}
		}
		return phty;
	}
	
	public FunNType visit(FunNType funnty, Integer ht) {
		List<UnifyType> param = new ArrayList<>(funnty.getTypeParams().get().length);
		param.addAll(Arrays.asList(funnty.getTypeParams().get()));
		UnifyType resultType = param.remove(param.size()-1);
		Integer htInverse = inverseVariance(ht);
		param = param.stream()
				     .map(x -> x.accept(this, htInverse))
				     .collect(Collectors.toCollection(ArrayList::new));
		param.add(resultType.accept(this, ht));
		return FunNType.getFunNType(new TypeParams(param));
	}
	
	
}
