package jfractionlab.exerciseGenerator;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

import jfractionlab.GreatestCommonDivisor;
import jfractionlab.JFractionLab;

abstract class GeneratorObject{

	abstract Exercises getOneExercise(
			int range1,
			int range2
	);
	
	
	
	public String writeReducingTextMultiplyDivide(boolean showCalculation, int n1, int d1, int n2, int d2){
		String strReturn;
		int fn1 = 1;
		int fd1 = 1;
		int fn2 = 1;
		int fd2 = 1;
		
		boolean n1IsReduced = false;
		boolean d1IsReduced = false;
		boolean n2IsReduced = false;
		boolean d2IsReduced = false;
		
		//sort the GreatestCommonDivisors
		ArrayList<GreatestCommonDivisor> al_gcd = new ArrayList<GreatestCommonDivisor>();
		al_gcd.add(new GreatestCommonDivisor("n1d1",
				JFractionLab.greatestCommonDivisor(n1, d1)));
		al_gcd.add(new GreatestCommonDivisor("n1d2",
				JFractionLab.greatestCommonDivisor(n1, d2)));
		al_gcd.add(new GreatestCommonDivisor("n2d1",
				JFractionLab.greatestCommonDivisor(n2, d1)));
		al_gcd.add(new GreatestCommonDivisor("n2d2",
				JFractionLab.greatestCommonDivisor(n2, d2)));
		Comparator<GreatestCommonDivisor> reverse = Collections.reverseOrder();
		Collections.sort(al_gcd, reverse);

		//reduce: start with the biggest GCD
		for (int i = 0; i< al_gcd.size(); i++){
			String nameOfGCD = al_gcd.get(i).getName();
			if(nameOfGCD.equals("n1d1")){
				if(!n1IsReduced && !d1IsReduced){
					n1 = n1/al_gcd.get(i).getGcd();
					fn1 = al_gcd.get(i).getGcd();
					n1IsReduced = true;
					
					d1 = d1/al_gcd.get(i).getGcd();
					fd1 = al_gcd.get(i).getGcd();
					d1IsReduced = true;
				}
			}else if(nameOfGCD.equals("n1d2")){
				if(!n1IsReduced && !d2IsReduced){
					n1 = n1/al_gcd.get(i).getGcd();
					fn1 = al_gcd.get(i).getGcd();
					n1IsReduced = true;
					
					d2 = d2/al_gcd.get(i).getGcd();
					fd2 = al_gcd.get(i).getGcd();
					d2IsReduced = true;
				}
			}else if(nameOfGCD.equals("n2d1")){
				if(!n2IsReduced && !d1IsReduced){
					n2 = n2/al_gcd.get(i).getGcd();
					fn2 = al_gcd.get(i).getGcd();
					n2IsReduced = true;
					
					d1 = d1/al_gcd.get(i).getGcd();
					fd1 = al_gcd.get(i).getGcd();
					d1IsReduced = true;
				}
			}else if(nameOfGCD.equals("n2d2")){
				if(!n2IsReduced && !d2IsReduced){
					n2 = n2/al_gcd.get(i).getGcd();
					fn2 = al_gcd.get(i).getGcd();
					n2IsReduced = true;
					
					d2 = d2/al_gcd.get(i).getGcd();
					fd2 = al_gcd.get(i).getGcd();
					d2IsReduced = true;
				}
			}
		}
		if(showCalculation){
			if(fn1 == 1 && fd1 == 1 && fn2 == 1 && fd2 == 1){
	//			System.out.println("nichts wurde gekürzt");
				strReturn = "";
			}else{
				strReturn ="{{";
				
				if(fn1 > 1){strReturn += n1+" cdot "+fn1;}
				else{strReturn += n1;}
				
				strReturn += "}over{";
				
				if(fd1 > 1){strReturn += d1+" cdot "+fd1;}
				else{strReturn += d1;}
				
				strReturn += "}}"; //close denominator
				strReturn += "cdot";
				strReturn +="{{";
				
				if(fn2 > 1){strReturn += n2+" cdot "+fn2;}
				else{strReturn += n2;}
				
				strReturn += "}over{";
				
				if(fd2 > 1){strReturn += d2+" cdot "+fd2;}
				else{strReturn += d2;}
				
				strReturn += "}}"; //close denominator
				strReturn += " = ";
				strReturn += "{"+n1+" cdot "+n2+"}over{"+d1+" cdot "+d2+"}";
				
				if((n1*n2)>(d1*d2)){
					strReturn += " = ";
				}
			}
			if((n1*n2)>(d1*d2)){
				strReturn += "{"+(n1 * n2)+"}over{"+(d1 * d2)+"}";
			}
		}else{
//			strReturn = "{"+(n1*n2)+"}over{"+(d1*d2)+"}";
			strReturn = writeReducingTextResult(showCalculation, (n1*n2), (d1*d2));
		}
//		System.out.println("strReturn = "+strReturn);
		return strReturn;
	}
	
	public String writeReducingTextResult(boolean longsolution, int n, int lcd){
		String strLong	= "";
		String strQuick	= "";
		
		int ggt = JFractionLab.greatestCommonDivisor(n, lcd);
		if(n < lcd){
			int n_reduced = n;
			int lcd_reduced = lcd;
			if(n != n/ggt){
				//result is reducable
				n_reduced = n/ggt;
				lcd_reduced = lcd/ggt;
				strLong += " = {"+n_reduced+" cdot "+ggt+"}over{"+lcd_reduced+" cdot "+ggt+"}";
				strQuick	+= "{"+n_reduced+"}over{"+lcd_reduced+"}";
				strLong	+= " = {"+n_reduced+"}over{"+lcd_reduced+"}";
			}else{
				//result is not reducable
				strQuick	+= "{"+(n/ggt)+"}over{"+(lcd/ggt)+"}";
			}
		}else if (n > lcd){
			int n_reduced = n;
			int lcd_reduced = lcd;
			int fullnb = n_reduced / lcd_reduced;
			strLong += " = ";
			if(n != n/ggt){
				//result is reducable
				n_reduced = n/ggt;
				lcd_reduced = lcd/ggt;
				strLong += "{"+n_reduced+" cdot "+ggt+"}over{"+lcd_reduced+" cdot "+ggt+"} = ";
				strLong += "{"+n_reduced+"}over{"+lcd_reduced+"} = ";
			}
			int lastN = n_reduced%lcd_reduced;
			if(lastN ==0){
				strQuick += fullnb;
				strLong += fullnb;
			}else{
				strLong += "{"+(fullnb*lcd_reduced)+"}over{"+lcd_reduced+"} + ";
				strLong += "{"+(lastN)+"}over{"+lcd_reduced+"} = ";
				strQuick	+= fullnb+"{"+(lastN)+"}over{"+lcd_reduced+"}";
				strLong	+= fullnb+"{"+(lastN)+"}over{"+lcd_reduced+"}";
			}
		
		}else if(n == lcd){
			strQuick	+= "1";
			strLong	+= " = 1";
		}
		if(longsolution){
			return strLong;
		}else{
			return strQuick;
		}
	}
}
