package de.dhbwstuttgart.typeinference.unify;

import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ForkJoinPool;

import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.typeinference.constraints.Constraint;
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
import de.dhbwstuttgart.typeinference.constraints.Pair;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.FiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;

public class TypeUnify {
	
	/**
	 * unify parallel ohne result modell
	 * @param undConstrains
	 * @param oderConstraints
	 * @param fc
	 * @param logFile
	 * @param log
	 * @param cons
	 * @return
	 */
	public Set<Set<UnifyPair>> unify(Set<UnifyPair> undConstrains, List<Set<Set<UnifyPair>>> oderConstraints, IFiniteClosure fc, Writer logFile, Boolean log, UnifyResultModel ret, UnifyTaskModel usedTasks) {
		TypeUnifyTask unifyTask = new TypeUnifyTask(undConstrains, oderConstraints, fc, true, logFile, log, 0, ret, usedTasks);
		ForkJoinPool pool = new ForkJoinPool();
		pool.invoke(unifyTask);
		Set<Set<UnifyPair>> res =  unifyTask.join();
		try {
			logFile.write("\nnoShortendElements: " + unifyTask.noShortendElements + "\n");
			logFile.flush();
		}
		catch (IOException e) {
			System.err.println("no log-File");
		}
		return res;
	}
	
	/**
	 * unify asynchron mit Rückgabe UnifyResultModel ohne dass alle results gesammelt sind
	 * @param undConstrains
	 * @param oderConstraints
	 * @param fc
	 * @param logFile
	 * @param log
	 * @param cons
	 * @param ret
	 * @return
	 */
	public UnifyResultModel unifyAsync(Set<UnifyPair> undConstrains, List<Set<Set<UnifyPair>>> oderConstraints, IFiniteClosure fc, Writer logFile, Boolean log, UnifyResultModel ret, UnifyTaskModel usedTasks) {
		TypeUnifyTask unifyTask = new TypeUnifyTask(undConstrains, oderConstraints, fc, true, logFile, log, 0, ret, usedTasks);
		ForkJoinPool pool = new ForkJoinPool();
		pool.invoke(unifyTask);
		return ret;
	}
	
	/**
	 * unify parallel mit Rückgabe UnifyResultModel nachdem alle results gesammelt sind
	 * @param undConstrains
	 * @param oderConstraints
	 * @param fc
	 * @param logFile
	 * @param log
	 * @param cons
	 * @param ret
	 * @return
	 */
	public UnifyResultModel unifyParallel(Set<UnifyPair> undConstrains, List<Set<Set<UnifyPair>>> oderConstraints, IFiniteClosure fc, Writer logFile, Boolean log, UnifyResultModel ret, UnifyTaskModel usedTasks) {
		TypeUnifyTask unifyTask = new TypeUnifyTask(undConstrains, oderConstraints, fc, true, logFile, log, 0, ret, usedTasks);
		ForkJoinPool pool = new ForkJoinPool();
		pool.invoke(unifyTask);
		Set<Set<UnifyPair>> res =  unifyTask.join();
		try {
			logFile.write("\nnoShortendElements: " + unifyTask.noShortendElements +"\n");
			logFile.flush();
		}
		catch (IOException e) {
			System.err.println("no log-File");
		}
		return ret;
	}
	
	/*
	public Set<Set<UnifyPair>> unifySequential(Set<UnifyPair> eq, IFiniteClosure fc, FileWriter logFile, Boolean log) {
		TypeUnifyTask unifyTask = new TypeUnifyTask(eq, fc, false, logFile, log);
		Set<Set<UnifyPair>> res = unifyTask.compute();
		return res;
	}
	*/
	
	/**
	 * unify sequentiell mit oderconstraints
	 * @param undConstrains
	 * @param oderConstraints
	 * @param fc
	 * @param logFile
	 * @param log
	 * @param cons
	 * @return
	 */
	public Set<Set<UnifyPair>> unifyOderConstraints(Set<UnifyPair> undConstrains, List<Set<Set<UnifyPair>>> oderConstraints, IFiniteClosure fc, Writer logFile, Boolean log, UnifyResultModel ret, UnifyTaskModel usedTasks) {
		TypeUnifyTask unifyTask = new TypeUnifyTask(undConstrains, oderConstraints, fc, false, logFile, log, 0, ret, usedTasks);
		Set<Set<UnifyPair>> res = unifyTask.compute();
		try {
			logFile.write("\nnoShortendElements: " + unifyTask.noShortendElements +"\n");
			logFile.flush();
		}
		catch (IOException e) {
			System.err.println("no log-File");
		}
		return res;
	}

}
