package Bubulle;

import java.io.IOException;
import java.util.ArrayList;

public class Tracker {

	//régularité
	//plus les angles identiques = score bas
	//plus distance identiques = score bas
	//ATTENTION !!! b3 et b4 --> 2 delta t
	
	private static ArrayList<Trajectoire> solution = new ArrayList<Trajectoire>();
	private static ArrayList<Bulle> population;
	private static final int maxBulle = 5;
	private static final double ANGLE = 180;
	private static final double DISTANCE = 0.4;
	

	public static void main(String[] args) throws IOException {
		
		final String norma = "bubu";//"norma_N5_tau4_dt2_delai820_00000";
		final String ext = ".txt";
		int max = 1; 
		
		String name = norma+max+ext;
		
		//Lecture et stockage en mémoire de toute les bulles
		Lecture.launch(name);
		
		demarrage(Recherche.file);
	}
	
	private static void score(Trajectoire t) {
		
		ArrayList<Bulle> list = t.getList();
		double score = 0.0;
		
		//Angle
		for(int i = 0; i < 2; i++) {
			score+= Math.abs( Angle.degre(list.get(i), list.get(i+1), list.get(i+2)) - Angle.degre(list.get(i+1), list.get(i+2), list.get(i+3)) );
		}
		
		//Distance
		for(int i = 0; i < 3; i++) {
			score+= Math.abs( list.get(i).distanceXYZ(list.get(i+1)) - list.get(i+1).distanceXYZ(list.get(i+2)) );
		}
		
		t.setScore(score);
	}
	
	
	private static void demarrage(ArrayList<Bulle> popInit) {
		
		population = popInit;
		
		for(Bulle b : popInit) {
			backtracking2(b.getNo(), new Trajectoire());
		}
			
	}
	
	//Arret trajectoire pleine 5
	private static boolean /*void*/ backtracking(int act, Trajectoire tracer) {//TODO DOUBLON
	
		/*------------------*/
		//DEBUG
		for(Bulle b : tracer.getList())
			System.out.print(b.getNo() + " ");
		System.out.println();
		/*------------------*/
		/*------------------*/
		
		if(act > population.size()) {
			System.out.println("-0-");
			
			//Suppression du dernier
			Bulle b = tracer.removeLast();
			//On continue					
			return backtracking(b.getNo()+1, tracer);
		}
			
		
		//Liste vide et non dernier élément de la population
		if(tracer.getList().isEmpty() && act != population.size()) {
			tracer.setList(population.get(act-1));
			
			System.out.println("-1-");
			
			return backtracking(act+1, tracer);
		}
		
		//Liste vide et dernier élément de la population
		if(tracer.getList().isEmpty() && act == population.size()) {
			System.out.println("-2-");
			return false;
		}
		
		//La liste n'est pas totalement rempli
		if(tracer.getList().size() < 5) {
			
			System.out.println("-3-");
			//TODO vérification doublon & vérification ajout correct
			tracer.setList(population.get(act-1));
			
			
			return backtracking(act+1, tracer);
			
		}
		
		//On à rempli le tracer (on continue de chercher des chemins)
		if(tracer.getList().size() == maxBulle) {
			//Ajout de la solution
			solution.add(tracer);
			
			System.out.println("+5+");
			
			//Suppression du dernier
			Bulle b = tracer.removeLast();
			//On continue					
			return backtracking(b.getNo()+1, tracer);
			
		}
		
		
		return true;
		
		/*
		
		//Choix de la bulle suivante
		Bulle suiv;
		
		if(act.getNo() == population.size()) {
			suiv = population.get(0);
		}
		else {
			suiv = population.get(act.getNo());
		}
		
		
		
		//Cas de la liste vide
		if(tracer.getList().size() == 0) {
			tracer.setList(act);
			
			backtracking(population.get(0), tracer);
		}
		//Cas de la liste non vide et non pleine
		else if(tracer.getList().size() < 5) {
			
			if(!tracer.contains(act)) {
				tracer.setList(act);
			}
			
			//Si fin de la liste
			if(act.getNo() == population.size()) {
				//Suppresion de la dernière
				Bulle b = tracer.removeLast();
				//Ajout de la suivante de la dernière
				tracer.setList(population.get(b.getNo()));
				backtracking(population.get(0), tracer);
			}
			else {
				backtracking(population.get(act.getNo()), tracer);
			}
			
			
		}
		
		
		
		
		/*
		//Si la liste est finalement pleine
		if(tracer.getList().size() == 5) {
			
			//Ajout d'une solution possible
			solution.add(tracer);
			
			
			//DEBUG
			for(Bulle b : tracer.getList())
				System.out.print(b.getNo() + " ");
			System.out.println();
			
			
			
			
			//Suppression de la dernière de la solution actuelle
			Bulle tmp = tracer.removeLast();
			
			//Continuation avec les bulles restantes
			int index = tmp.getNo();
			
			if(act.getNo() == population.size()) {
				//suiv = population.get(0);
				
				tmp = tracer.removeLast();
				index = 0;
			}
			
			suiv = population.get(index);
			
			
		}
		
		
		//On a re-vider toute la liste et on est de retour au début
		if(tracer.getList().isEmpty() && suiv.getNo() == 1) {
			//fin
			System.out.println("fin 1");
		}
		//On a une liste non remplie et que la prochaine première n'existe pas
		if(tracer.getList().size() < 5 && (act.getNo()+1) > population.size()) {
			//fin
			System.out.println("fin 2");
		}
		
		backtracking(suiv, tracer);
		
		
		/*
		int suiv = act.getNo()+1;
		
		//Cas de fin de population
		if( suiv > population.size() )
			suiv = 0;
		
		
		
		backtracking(population.get(suiv), tracer);
		*/
		
			
	}
	
	
	
	
	
	
	/*
	 * act : id de la bulle (1 a 10)
	 * population : liste des bulles (0 a 9) taille 10
	 * tracer : liste de bulle
	 */
	//Arret trajectoire pleine 5
		private static boolean backtracking2(int act, Trajectoire tracer) {
                        /*------------------*/
                        //DEBUG
                        tracer.getList().stream().forEach((b) -> {
                            System.out.print(b.getNo() + " ");
                        });
			System.out.println();
			/*------------------*/
			/*------------------*/
			
			
			if(act <= population.size()) {
				if(estok(act, tracer)) {//TODO
					tracer.setList(population.get(act-1));
					
					
					if(tracer.getList().size() == 5) {
						solution.add(tracer);
						
                                            /*------------------*/
                                            //DEBUG
                                            tracer.getList().stream().forEach((b) -> {
                                                System.out.print(b.getNo() + " ");
                                            });
                                            
                                            System.out.println("--add--");
                                            /*------------------*/
                                            /*------------------*/


                                            Bulle b = tracer.removeLast();
                                            return backtracking2(b.getNo()+1, tracer);
					}
					else {
						return backtracking2(1, tracer);
					}
				}else {
					return backtracking2(act+1, tracer);
				}
			}else {
                                boolean stop = false;
                                
				//on recupere le no +1 du dernier element
				while(!stop && tracer.getLast().getNo() + 1 > population.size()) {
					//Bulle b1 = tracer.removeLast(); //b1 pas utiliser
                                        
                                        System.out.println("-- PING --"); //DEBUG
                                        
                                        tracer.removeLast();
					if(tracer.getList().isEmpty()){
                                            stop = true;
                                        }
				}
                                
                                
                                if(stop){
                                    System.out.println("-- END --"); //DEBUG
                                    return false;
                                }
                                else{
                                    Bulle b3 = tracer.removeLast();
                                    return backtracking2(b3.getNo()+1, tracer);
                                }
			}
			
		}
		
		public static boolean estok(int act, Trajectoire tracer) {//TODO 2 delta t
			/*
			 * distance si |distance| > DISTANCE -> false
			 * angle si |angle| > ANGLE -> false
			 * doublon si l'elment est deja dans la liste -> false
			 */
			if(tracer.getList().isEmpty()) {
				return true;
			}
			else if(tracer.getList().size() == 1) {
				//doublon
				if(tracer.contains(population.get(act-1))) {
					return false;
				}
				
				
				
				//System.out.println("---> " + Math.abs(tracer.getLast().distanceXYZ(population.get(act-1))));
				//distance
                                
                                double dist = Math.abs(tracer.getLast().distanceXYZ(population.get(act-1)));
                                
				if(dist > DISTANCE) {
					System.out.println("dist 1  : " + dist);
					return false;
				}
			}
			else {
				//doublon
				if(tracer.contains(population.get(act-1))) {
					System.out.println("contain");
					return false;
				}
				
				//angle
				if(Math.abs(Angle.degre(tracer.getElementPosition(2), tracer.getElementPosition(1), population.get(act-1))) > ANGLE) {
					System.out.println("angle");
					return false;
				}
				
				//distance
				if(Math.abs(tracer.getLast().distanceXYZ(population.get(act-1))) > DISTANCE) {
					System.out.println("dist 2   : " + Math.abs(tracer.getLast().distanceXYZ(population.get(act-1))));
					return false;
				}
				
			}
			return true;
			
		}
	
	
} 
