package structure;

import java.util.*;

public class Grid {

	
	
	private ArrayList<Router> grid=new ArrayList<>();
	private ArrayList<ArrayList<Integer>> links=new ArrayList<>();
	
	private Random rand = new Random();
	
	private final int maxWeight=100;
	
	/**
	 * Build a 3x3 Grid
	 */
	public Grid(){
			
		// Build Grid
		for(int i=0;i<9;i++){
			this.grid.add(new Router());
		}
		
		// First line
		this.buildLinkWithRandomWeight(grid.get(0), grid.get(1));
		this.buildLinkWithRandomWeight(grid.get(1), grid.get(2));

		// Second line
		this.buildLinkWithRandomWeight(grid.get(3), grid.get(4));
		this.buildLinkWithRandomWeight(grid.get(4), grid.get(5));
		
		// Third line
		this.buildLinkWithRandomWeight(grid.get(6), grid.get(7));
		this.buildLinkWithRandomWeight(grid.get(7), grid.get(8));
		
		// First column
		this.buildLinkWithRandomWeight(grid.get(0), grid.get(3));
		this.buildLinkWithRandomWeight(grid.get(3), grid.get(6));
		
		// Second column
		this.buildLinkWithRandomWeight(grid.get(1), grid.get(4));
		this.buildLinkWithRandomWeight(grid.get(4), grid.get(7));
		
		// Third column
		this.buildLinkWithRandomWeight(grid.get(2), grid.get(5));
		this.buildLinkWithRandomWeight(grid.get(5), grid.get(8));

		this.buildLinks();
	}
	
	
	private void buildLinks(){
		
		// Link1
		ArrayList<Integer> link1=new ArrayList<>();
		link1.add(0);link1.add(1);link1.add(2);link1.add(5);link1.add(4);link1.add(3);link1.add(6);link1.add(7);link1.add(8);
		this.links.add(link1);
		
		// Link2
		ArrayList<Integer> link2=new ArrayList<>();
		link2.add(0);link2.add(1);link2.add(2);link2.add(5);link2.add(4);link2.add(7);link2.add(8);
		this.links.add(link2);
		
		// link3
		ArrayList<Integer> link3=new ArrayList<>();
		link3.add(0);link3.add(1);link3.add(2);link3.add(5);link3.add(8);
		this.links.add(link3);
		
		// link4
		ArrayList<Integer> link4=new ArrayList<>();
		link4.add(0);link4.add(1);link4.add(4);link4.add(5);link4.add(8);
		this.links.add(link4);
		
		// link5
		ArrayList<Integer> link5=new ArrayList<>();
		link5.add(0);link5.add(3);link5.add(4);link5.add(5);link5.add(8);
		this.links.add(link5);
		
		// link6
		ArrayList<Integer> link6=new ArrayList<>();
		link6.add(0);link6.add(3);link6.add(4);link6.add(7);link6.add(8);
		this.links.add(link6);
		
		// link7
		ArrayList<Integer> link7=new ArrayList<>();
		link7.add(0);link7.add(3);link7.add(6);link7.add(7);link7.add(8);
		this.links.add(link7);
		
		// link8
		ArrayList<Integer> link8=new ArrayList<>();
		link8.add(0);link8.add(3);link8.add(6);link8.add(7);link8.add(4);link8.add(5);link8.add(8);
		this.links.add(link8);
		
		// link9
		ArrayList<Integer> link9=new ArrayList<>();
		link9.add(0);link9.add(3);link9.add(6);link9.add(7);link9.add(4);link9.add(1);link9.add(2);link9.add(5);link9.add(8);
		this.links.add(link9);
		
		// link10
		ArrayList<Integer> link10=new ArrayList<>();
		link10.add(0);link10.add(3);link10.add(4);link10.add(1);link10.add(2);link10.add(5);link10.add(8);
		this.links.add(link10);
		
		// link11
		ArrayList<Integer> link11=new ArrayList<>();
		link11.add(0);link11.add(1);link11.add(4);link11.add(3);link11.add(6);link11.add(7);link11.add(8);
		this.links.add(link11);
	}
	
	
	private void buildLinkWithRandomWeight(Router router1, Router router2){
		router1.buildLink(router2, rand.nextInt(this.maxWeight));
	}
	
	
	
	public int getBestLinkIndex(){
		int currentBestLink=0;
		int currentBestLinkBottleneck=0;
		for(int i=0;i<this.links.size();i++){
			ArrayList<Integer> currentLink=this.links.get(i);
			int currentLinkBottleneck=this.getMaxBottleneck(currentLink);
			if(currentBestLinkBottleneck<currentLinkBottleneck){
				currentBestLink=i;
				currentBestLinkBottleneck=currentLinkBottleneck;
			}
		}
		
		return currentBestLink;
	}
	
	/*private int getMaxBottleneck(ArrayList<Integer> link){
		int max=this.getWeigthOfLink(link.get(0), link.get(1));
		for(int j=1;j<link.size()-1;j++){
			int currentMax=this.getWeigthOfLink(link.get(j), link.get(j+1));
			if(max<currentMax){
				max=currentMax;
			}
			
		}
		return max;
	}*/
	private int getMaxBottleneck(ArrayList<Integer> link){
		int max=this.getWeigthOfLink(link.get(0), link.get(1));
		for(int j=1;j<link.size()-1;j++){
			int currentMax=this.getWeigthOfLink(link.get(j), link.get(j+1));
			if(max>currentMax){
				max=currentMax;
			}
			
		}
		return max;
	}
	
	private int getWeigthOfLink(int router1,int router2){
		return this.grid.get(router1).getWeight(this.grid.get(router2));
	}
	
	
	public void printLinkWeight(){
		for(int i=0;i<this.links.size();i++){
			ArrayList<Integer> link=this.links.get(i);
			System.out.print("Link number " + i + " ==> ");
			for(int j=0;j<link.size()-1;j++){
				System.out.print(this.getWeigthOfLink(link.get(j), link.get(j+1)) + "   ");
			}
			System.out.println("                                                       Goulot :"+this.getMaxBottleneck(link));
			//System.out.println();
		}
	}


	
	
	public boolean isEdgeOfLink(ArrayList<Integer>link, Router src, Router dest){
		for(int j=0;j<link.size()-1;j++){
			Router current=this.grid.get(link.get(j));
			if(src.name.equals(current.name)){
				if(j<link.size()-1){
					Router currentDest=this.grid.get(link.get(j+1));

					if(currentDest.name.equals(dest.name)){
						return true;
					}
				}
			}
		}
		for(int j=0;j<link.size()-1;j++){
			Router current=this.grid.get(link.get(j));
			if(dest.name.equals(current.name)){
				if(j<link.size()-1){
					Router currentDest=this.grid.get(link.get(j+1));

					if(currentDest.name.equals(src.name)){
						return true;
					}
				}
			}
		}
		return false;
	}
	
	
	
	public ArrayList<Router> getGrid() {
		return grid;
	}


	public void setGrid(ArrayList<Router> grid) {
		this.grid = grid;
	}


	public ArrayList<ArrayList<Integer>> getLinks() {
		return links;
	}


	public void setLinks(ArrayList<ArrayList<Integer>> links) {
		this.links = links;
	}

	
	
}
