//
// Visuzalization module for TETDM 
// XDrawDisplay.java Version 0.30
// Copyright(C) 2011 WATARU SUNAYAMA ALL RIGHTS RESERVED.
//
// This program is provided under the licenses.
// You Should read the README file.
//

package module.VisualizationModules.XDrawDisplay;

import source.*;
import source.TextData.*;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.text.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;


public class XDrawDisplay extends VisualizationModule implements MouseListener, MouseMotionListener
{
	//Related to drawing of background
	Toolkit tk;
	public Image image1;	
	

	//For objects operation
	int mousex, mousey;			//Coordinates for a mouse
	int old_mousex, old_mousey;	//Last Coordinates for a mosue
	int dx, dy;					//Distance for mouse moving
	
	int touchNumber;				//Node Number of being touched
    int lastTouchNumber;

	boolean moving;			//Flag for node moving
	boolean dragging;		//Flag for field moving	

	
	int node_keyidlist[];
	int topic_num;	
	
	NewMapData map;

    int sbaseList[];
    int topicList[];
    int backList[];
    int featList[];
	
	public XDrawDisplay()
	{
		setModuleID(8);	
	}

	public void initializePanel()
	{
		tk = getToolkit();		
		image1 = tk.getImage(myModulePath+"fuji.jpg");
		addMouseListener(this);			//MouseListener
		addMouseMotionListener(this);	//MouseMotionListener	
	}	
	
	public void initializeData()
	{
		touchNumber = -1;
		lastTouchNumber = -1;
		
		moving = false;
		dragging = false;
		
		topic_num = 0;
	}

	public void displayOperations(int optionNumber)
	{
		switch(optionNumber)
		{
			case 0:
			    makeMapData();
			    repaint();
			    break;
		}		
	}

	public void setData(int dataID, int data[])
	{
		switch(dataID)
		{
		    case 50:
			topicList = data;
			break;
		
		    case 51:
			backList = data;
		        break;

		    case 52:
			featList = data;
			break;

		    case 77:
			sbaseList = data;
			break;
		}
	}
    
    void makeMapData()
    {
		int number, c;

		number = sbaseList.length + topicList.length + backList.length + featList.length;
		map = new NewMapData(number);
		c = 0;
	
		for(int i=0;i<sbaseList.length;i++,c++)
		{
			map.node[c].id = sbaseList[i];
			map.node[c].name = text.keyword[sbaseList[i]].word;
			map.node[c].x = sizeX/2-10;
			map.node[c].y = (30*sizeY/100) / sbaseList.length * i + 25;
			map.node[c].color = new Color(0xff,0x66,0x00);
	    }

		for(int i=0;i<topicList.length;i++,c++)
	    {
			map.node[c].id = topicList[i];
			map.node[c].name = text.keyword[topicList[i]].word;
			map.node[c].x = sizeX/2-10;
			map.node[c].y = (30*sizeY/100) + 50 + i*25;
			map.node[c].color = new Color(0xa5,0x2a,0x2a);
	    }

		for(int i=0;i<backList.length;i++,c++)
	    {
			map.node[c].id = backList[i];
			map.node[c].name = text.keyword[backList[i]].word;
			map.node[c].x = sizeX/2-30 + (80+((sizeX-200)/(backList.length*2))*i)*(int)Math.pow(-1.0,(double)i);
			map.node[c].y = (30*sizeY/100) + i*15 + 50;
			map.node[c].color = new Color(0x00,0x00,0xcc);
	    }

		for(int i=0;i<featList.length;i++,c++)
	    {
			map.node[c].id = featList[i];
			map.node[c].name = text.keyword[featList[i]].word;
			map.node[c].x = sizeX/2-30 + (80+((sizeX-200)/(featList.length*2))*i)*(int)Math.pow(-1.0,(double)i);
			map.node[c].y = (30*sizeY/100) + i*15 + 200;
			map.node[c].color = new Color(0x00,0xdb,0x47);
	    }
    }

	//////////DRAWING

	void calcu_coordinate()
	{		
		for(int i=0;i<map.node_num;i++)
		{
			map.node[i].x *= changeX;
			map.node[i].y *= changeY;
		}
	}	
	
	void draw_background(Graphics2D g2)
	{
		g2.drawImage(image1,0,0,sizeX,sizeY,this);
		g2.setColor(Color.red);
		g2.drawLine(0,30*sizeY/100,sizeX,30*sizeY/100);
	}

	//Display nodes
	public void draw_node(Graphics2D g2, int n)
	{
		g2.setColor(map.node[n].color);
		g2.fillOval((int)map.node[n].x - (int)map.node[n].radius, 
						(int)map.node[n].y - (int)map.node[n].radius, (int)map.node[n].radius*2, (int)map.node[n].radius*2);
	}
	
	public void draw_nodes(Graphics2D g2)
	{
		for(int i=0;i<map.node_num;i++)
			draw_node(g2, i);
	}
	
	////Dispaly node names
	public void draw_node_name(Graphics2D g2, int n)
	{
		g2.setFont(new Font("Dialog", Font.BOLD, (int)(24-2*map.node_num/25.0)));
		g2.drawString(map.node[n].name, (int)map.node[n].x+(int)map.node[n].radius, (int)map.node[n].y+(int)map.node[n].radius);
	}
	
	public void draw_node_names(Graphics2D g2)
	{
		for(int i=0;i<map.node_num;i++)
		{
			g2.setColor(Color.black);
			draw_node_name(g2, i);
		}
	}	
	
	public void draw_touch_node(Graphics2D g2)
	{
		if(touchNumber < 0)
			return;
		
		draw_node(g2, touchNumber);
	}
	
	//Display node names touched by a mouse
	public void draw_touch_nodename(Graphics2D g2)
	{
		if(touchNumber < 0)
			return;
		
		g2.setColor(Color.red);
		draw_node_name(g2, touchNumber);
	}
	
	
	public void paintComponent(Graphics g)
	{
		Graphics2D g2 = (Graphics2D)g;

		boolean change = getPanelSize();
		
		if(change)
			calcu_coordinate();		
		
		draw_background(g2);
		draw_nodes(g2);			//Display nodes
		draw_node_names(g2);	//Display node names
		draw_touch_node(g2);	//Display nodes touched by a mouse
		draw_touch_nodename(g2);	//Display node names touched by a mouse		
	}
	
	public void update(Graphics g)		//Avoid from blinking
	{
		paintComponent(g);
	}
	
	//MouseListener
	public void mousePressed(MouseEvent me)	//Press
	{
		mousex = me.getX();
		mousey = me.getY();
		
		if(touchNumber == -1)
		{
			old_mousex = mousex;
			old_mousey = mousey;
			dragging = true;
			return;
		}
		moving = true;
	}
	
	public void mouseReleased(MouseEvent me)	//Release
	{
		if(moving == true)
			moving = false;
		
		if(dragging == true)
			dragging = false;
	}
	
	public void mouseEntered(MouseEvent me){}	//Enter an area
	public void mouseExited(MouseEvent me){}	//Exit an area
	


	public void mouseClicked(MouseEvent me)	//Click
	{
		int click_num;
		
		mousex = me.getX();
		mousey = me.getY();
		click_num = CatchNode(mousex,mousey);
		
		if(click_num == -1)
		{
			topic_num = 0;
			for(int i=0;i<map.node_num;i++)
				if(map.node[i].y < 30*sizeY/100)
					topic_num++;

			node_keyidlist = new int[topic_num];
			
			int c=0;
			for(int i=0;i<map.node_num;i++)
				if(map.node[i].y < 30*sizeY/100)				
					node_keyidlist[c++] = map.node[i].id;
			
			for(int i=0;i<map.node_num;i++)///////////////////////////////LINKAGE
				if(map.node[i].y < 30*sizeY/100)
					text.focus.focusKeywords[map.node[i].id] = true;
				else
					text.focus.focusKeywords[map.node[i].id] = false;

			executeAllByClick();
		}
	}	
	
	//MouseMotionListener
	public void mouseDragged(MouseEvent me)	//Dragging
	{
		if(moving == true)		//Move a node
		{
			try{
				mousex = me.getX();
				mousey = me.getY();
				
				map.node[touchNumber].x = mousex;
				map.node[touchNumber].y = mousey;
				
				repaint();
			}
			catch(StackOverflowError e){
				System.out.println("Stack OVERFLOW");
			}
		}
		
		if(dragging == true)	//Move Field
		{
			mousex = me.getX();
			mousey = me.getY();
			dx = old_mousex - mousex;
			dy = old_mousey - mousey;
			old_mousex = mousex;
			old_mousey = mousey;
			
			for(int i=0;i<map.node_num;i++)
			{
				map.node[i].x -= dx;
				map.node[i].y -= dy;
			}
			repaint();
		}
	}
	
	public void mouseMoved(MouseEvent me)
	{
		mousex = me.getX();
		mousey = me.getY();
		touchNumber = CatchNode(mousex,mousey);
//		if(touchNumber >= 0 && touchNumber != lastTouchNumber)
//		{
//		    text.focus.mainFocusKeyword = map.node[touchNumber].id;
//		    //		    executeAll();
//		    executeOthers();
//		    repaintOthers();
//		    lastTouchNumber = touchNumber;
//		}
		repaint();
	}
	
	public int CatchNode(int mousex, int mousey)	//Investigate number of selected node
	{
		for(int i=0;i<map.node_num;i++)
			if((mousex > map.node[i].x - map.node[i].radius && mousex < map.node[i].x + map.node[i].radius 
												+ map.node[i].name.length()*(24-2*map.node_num/25.0)) && 
			   (mousey > map.node[i].y - map.node[i].radius && mousey < map.node[i].y + map.node[i].radius))
				return i;
	 
		return -1;
	}




class NewMapData
{
	class Node
	{
		String name;
		int id;
		double x;
		double y;
		double radius;
		Color color;
		
		Node()
		{
			x = 0;
			y = 0;
			radius = 12;
			color = Color.green;		
		}
	}	
	Node node[];
	int node_num;
	
	void init_nodes(int num)
	{
		node_num = num;
		node = new Node[node_num];
		
		for(int i=0;i<num;i++)
			node[i] = new Node();
	}
	
	NewMapData(int num)
	{
		init_nodes(num);
	}
}
	
}
