package automatvgi;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.LinkedList;

import javax.swing.ComponentInputMap;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JTextField;

import automatvgi.components.*;
import automatvgi.edit.LatexDump;
import automatvgi.tools.Point;
import automatvgi.tools.Vector;


public class Dessin extends JComponent implements MouseListener,KeyListener{
	static final long serialVersionUID=1;
	static private LinkedList<Dessin> lmjc= new LinkedList<Dessin>();
	
	private Automaton aut;
	private JComboBox alphabet;
	private JTextField stateLabel;
	private ChoiceOfAction coa;
	private Projection proj;
	
	void drawCircle(Graphics g, int x, int y, int r){
		g.drawOval(x-r,y-r,2*r,2*r);
	}
	
	public void setAlphabet(JComboBox al){
		alphabet=al;
	}

	public void setActions(ChoiceOfAction ca){
		coa=ca;
	}

	public void setStateLabel(JTextField sl){
		stateLabel=sl;
	}
	
	@Override
	protected void paintComponent(Graphics g){
		super.paintComponent(g);
		proj.setCentre(new Point(getWidth()/2,-getHeight()/2));
		g.setColor(new Color(200,255,255,100));
		g.fillRect(0,0,getWidth(),getHeight());
		aut.draw(g, proj, coa.move.isSelected() || coa.edition.isSelected() || coa.delete.isSelected());
		
	}
	
	public Dessin(){
		addMouseListener(this);
		setInputMap(WHEN_IN_FOCUSED_WINDOW,new ComponentInputMap(this));
		addKeyListener(this);
		//lac.add(new StateComponent(20,20));
		//StateComponent sc=new StateComponent(40,40);
		//sc.setLabel("pr");
		//lac.add(sc);	
		proj=new Projection();
		aut=new Automaton();
		//lac.add(proj);
		setFocusable(true);
		setPreferredSize(new Dimension(500,300));
		lmjc.add(this);

	}
	
	private StateComponent p;
	
	private StateComponent getStateByPoint(Point p){
		for(AutomatonComponent a: aut){
			if(a.kind()==AutomatonComponent.Kind.State){
				StateComponent s=(StateComponent)a;
				if( new Vector(s.getCenter(),p).norm()<2*proj.getArr())
					return s;
			}
		}
		return null;
	}
	private AutomatonComponent getComponentByPoint(Point p){
		for(AutomatonComponent a: aut){
			if(a.handle()!=null && new Vector(a.handle(),p).norm()<proj.getArr())
					return a;
		}
		return null;
	}
	
	public void 	mouseClicked(MouseEvent e){
		requestFocusInWindow();
		Point x=proj.getPoint(e.getX(),e.getY());
		if(coa.state.isSelected()){
			String s=stateLabel.getText();
			aut.addStateComponent(x,s);
			if(s!=null && s.length()==1){
				stateLabel.setText((new Character((char)(s.charAt(0)+1))).toString());
			}
		}
		if(coa.sinitial.isSelected()){
			StateComponent s=getStateByPoint(x);
			if(s!=null) aut.addLineComponent(new InitialComponent(s));
		}
		if(coa.sfinal.isSelected()){
			StateComponent s=getStateByPoint(x);
			if(s!=null) aut.addLineComponent(new FinalComponent(s));
		}
		if(coa.edition.isSelected()){
			AutomatonComponent s=getComponentByPoint(x);
			if(s!=null) s.edit();
		}
		if(coa.delete.isSelected()){
			AutomatonComponent s=getComponentByPoint(x);
			if(s!=null) aut.delete(s);
		}
		
		repaint();
	}
	public void 	mouseEntered(MouseEvent e){
		//empty
	}
	public void 	mouseExited(MouseEvent e){
		//empty
	}
	public void 	mousePressed(MouseEvent e){
		Point x=proj.getPoint(e.getX(), e.getY());
		p=getStateByPoint(x);
	}
	public void 	mouseReleased(MouseEvent e) {
		if(p==null) return;
		Point x=proj.getPoint(e.getX(), e.getY());
		if(coa.transition.isSelected()){
			StateComponent q=getStateByPoint(x);
			if(q==null) p=null;
			else{
				if(p!=q)
					aut.addTransitionComponent(new EdgeComponent(p,q,(String) alphabet.getSelectedItem()));
				else
					aut.addTransitionComponent(new LoopComponent(p,(String) alphabet.getSelectedItem()));
			}
		}
		if(coa.move.isSelected())
			p.setCenter(x);
		repaint();
	}
	public void 	keyPressed(KeyEvent e){
		switch(e.getKeyCode()){
		case KeyEvent.VK_UP:	proj.getTranslation().add(new Vector(0,-5));	break;
		case KeyEvent.VK_DOWN: 	proj.getTranslation().add(new Vector(0,-5));	break;
		case KeyEvent.VK_LEFT: 	proj.getTranslation().add(new Vector(-5,0));	break;
		case KeyEvent.VK_RIGHT: proj.getTranslation().add(new Vector(5,0));		break;
		case KeyEvent.VK_A: 	aut.fire('a');					break;
		case KeyEvent.VK_B: 	aut.fire('b');					break;
		case KeyEvent.VK_C: 	aut.fire('c');					break;
		case KeyEvent.VK_L: 	proj.getVi().rot(Math.PI/12);	break;
		case KeyEvent.VK_P:		new LatexDump(aut.toString());	break;
		case KeyEvent.VK_R: 	proj.getVi().rot(-Math.PI/12);	break;
		case KeyEvent.VK_Z: 	proj.getVi().scal(1.1);			break;
		case KeyEvent.VK_Y: 	proj.getVi().scal(1/1.1);		break;
		}
		//System.out.println("oupla");
		repaint();
	}
    public void 	keyReleased(KeyEvent e){
		//System.out.println("oupla");
    	//    	empty
    }
    public void 	keyTyped(KeyEvent e) {
		//System.out.println("oupla");
    	//empty
    }
    
	public static void redraw(){
		for(Dessin mjc : lmjc)
			mjc.repaint();
	}

}

