package automatvgi.components;

import java.awt.Color;
import java.awt.Graphics;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;

import road.action.Flip;
import road.tools.Edge;


//import automatvgi.LatexColor;
import automatvgi.LatexColor;
import automatvgi.Projection;
import automatvgi.tools.Point;



public class Automaton implements Iterable<AutomatonComponent>{

	private LinkedList<AutomatonComponent> lac=new LinkedList<AutomatonComponent>();
	private LinkedList<StateComponent> lsc=new LinkedList<StateComponent>();
	private LinkedList<TransitionComponent> ltc=new LinkedList<TransitionComponent>();
	private AutomatonFrame frame;
	private StateComponent[] tab; // beal
	
	public Automaton(){
		frame=new AutomatonFrame();
		lac.add(frame);
	}
	public Automaton(int n){
		frame=new AutomatonFrame();
		lac.add(frame);
		tab = new StateComponent[n];
		//System.out.println(q.size());
	}
	
    public StateComponent[] getTab() {
    	return tab;
    }
	
    public LinkedList<AutomatonComponent>  getLAC() {
    	return lac;
    }
    
    public LinkedList<StateComponent>  getLSC() {
    	return lsc;
    }
    
    public void setLSC(LinkedList<StateComponent> lsc){
    	this.lsc = lsc;
    }
    
    public LinkedList<TransitionComponent>  getLTC() {
    	return ltc;
    }
    
    public void setLTC(LinkedList<TransitionComponent> ltc){
    	this.ltc = ltc;
    }
    
    public void lightState(int s, LatexColor color){
    	tab[s].setFillColor(color);
	}
    
   
    
    
//    // pour 2 lettres a cause des a,b,c
//    public void doFlip(Flip flip) {
//		Edge e1 = flip.getE1();			
//		Edge e2 = flip.getE2();
//		int b1 = e1.getY();
//		int b2 = e2.getY();
//		System.out.print("Automaton:doFlip:"); System.out.println(flip);
//		if ((e1.getX() == e2.getX()) && (e1.getZ() == e2.getZ())) {
//			return;
//		}
//		for (AutomatonComponent ac : lac) {
//			if (ac instanceof TransitionComponent) {
//				TransitionComponent tac = (TransitionComponent) ac;
//				if ((tac.getSrc().equals(tab[e1.getX()])) 
//				   && (tac.getDst().equals(tab[e1.getZ()]))) {
//					if (b1 == 0) {
//						tac.setLineColor(LatexColor.getColorByName("Blue"));
//						if (tac.getLabel().equals("a")) {
//							tac.setLabel(new String()+(char) ((char) 'a'+ b2));
//						} else { // a,b,c  ...
//						}					
//					} else {
//						tac.setLineColor(LatexColor.getColorByName("Red"));
//						if (tac.getLabel().equals("b")) {
//							tac.setLabel(new String()+(char) ((char) 'a'+ b2));
//						} else { // a,b,c  ...
//						}	
//					}
//				}
//				if ((tac.getSrc().equals(tab[e2.getX()])) 
//						   && (tac.getDst().equals(tab[e2.getZ()]))) {
//							if (b2 == 0) {
//								tac.setLineColor(LatexColor.getColorByName("Blue"));
//								if (tac.getLabel().equals("a")) {
//									tac.setLabel(new String()+(char) ((char) 'a'+ b1));
//								} else { // a,b,c  ...
//								}					
//							} else {
//								tac.setLineColor(LatexColor.getColorByName("Red"));
//								if (tac.getLabel().equals("b")) {
//									tac.setLabel(new String()+(char) ((char) 'a'+ b1));
//								} else { // a,b,c  ...
//								}	
//							}
//						}
//			}
//		}
//    }
//						
//						
				
	  
    
	public void addStateComponent(Point x, String s){
		StateComponent ac=new StateComponent(x,s,frame.getStateDefaultStyle());
		//lac.add(ac);
		lsc.add(ac);
	}

	public void addStateComponent(Point x, String s, int i){
		StateComponent ac=new StateComponent(x,s,frame.getStateDefaultStyle());
		//lac.add(ac);
		lsc.add(ac);
		tab[i]= ac;
	}

	
	public void addLineComponent(LineComponent ac){
		ac.setDefaut(frame.getEdgeDefaultStyle());
		lac.add(ac);
	}

	
	public void addTransitionComponent(TransitionComponent ac){
		for(AutomatonComponent oac : ltc) // lac avant
			if (oac instanceof TransitionComponent) {
				TransitionComponent lc = (TransitionComponent) oac;
				if(lc.getSrc()==ac.getSrc() && lc.getDst()==ac.getDst()){
					lc.setLabel(lc.getLabel()+","+ac.getLabel());
					oac.setLineColor(LatexColor.getColorByName("Red"));
					return;
				}	
			}
		ac.setDefaut(frame.getEdgeDefaultStyle()); 
		//lac.add(ac);
		ltc.add(ac);
	}
	
	public Iterator<AutomatonComponent> iterator() {
		return lac.iterator();
	}
	
	public Iterator<StateComponent> stateIterator() {
		return lsc.iterator();
	}
	
	public Iterator<TransitionComponent> transitionIterator() {
		return ltc.iterator();
	}
	
	private static void drawHandle(Point p, Graphics g, Projection j){
		int x=j.getAbs(p), y=j.getOrd(p);
		g.setColor(Color.RED);
		g.drawRect(x-1,y-1,2,2);
	}

//	
//	public void draw(Graphics g, Projection j, boolean showHandles){
//		for(AutomatonComponent ac : lac){
//			ac.draw(g,j);
//			if(showHandles)
//				if(ac.handle()!=null)
//					drawHandle(ac.handle(), g, j);
//		}
//
//	}
	public void draw(Graphics g, Projection j, boolean showHandles){
		for(StateComponent ac : lsc){
			ac.draw(g,j);
			if(showHandles)
				if(ac.handle()!=null)
					drawHandle(ac.handle(), g, j);
		}
		for(TransitionComponent ac : ltc){
			ac.draw(g,j);
			if(showHandles)
				if(ac.handle()!=null)
					drawHandle(ac.handle(), g, j);
		}

	}
	
	@Override
	public String toString(){
		StringBuilder sb=new StringBuilder();
		for(AutomatonComponent ac : lac)
			sb.append(ac.toString());
		sb.append("\\end{VCPicture}\n");	
		return sb.toString();
	}

	public void fire(char a){
		HashMap<StateComponent, LinkedList<StateComponent>> map = new HashMap<StateComponent, LinkedList<StateComponent>>();
		for(AutomatonComponent ac : lac){
			if (ac instanceof TransitionComponent) {
				TransitionComponent tac = (TransitionComponent) ac;
				if(tac.getLabel().indexOf(""+a)!=-1){
					System.out.println(tac);
					LinkedList<StateComponent> ls=map.get(tac.getDst());
					if(ls == null){
						ls = new LinkedList<StateComponent>();
						map.put(tac.getDst(), ls);
					}
					for(StateComponent dst : tac.getSrc().getJetons())
						ls.add(dst);
				}
			}
		}
		for(AutomatonComponent ac : lac){
			if (ac instanceof StateComponent) {
				StateComponent sac = (StateComponent) ac;
				LinkedList<StateComponent> ls=map.get(sac);
				if(ls==null)
					ls= new LinkedList<StateComponent>();
				sac.setJetons(ls);					
			}
		}
	}
	
	public void delete(AutomatonComponent s){
		if (s instanceof LineComponent) {
			lac.remove(s);
		}
		else if (s instanceof StateComponent) {
			Iterator<AutomatonComponent> it=lac.iterator();
			while(it.hasNext()){
				AutomatonComponent bc=it.next();
				if (bc instanceof LineComponent){
					LineComponent lc=(LineComponent)bc;
					if(lc.getState().equals(s))
						it.remove();
					else if(bc instanceof EdgeComponent){
						EdgeComponent tc=(EdgeComponent) bc;
						if(tc.getDst().equals(s))
							it.remove();
					}
				}
			}
			lac.remove(s);
		}
	}
}
