

//
// Core Program for TETDM 
// PopUpWindow.java Version 0.44
// Copyright(C) 2012-2014 TETDM CORE MEMBER ALL RIGHTS RESERVED.
// This program is provided under the license.
//

package 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.*;

import net.reduls.igo.Tagger;
import net.reduls.igo.Morpheme;

public class PopUpForKnowledgeCreation extends JFrame implements ActionListener
{
	KnowledgeCreationPanel knowledgeCreationPanel;
	
	int posX, posY;
	int width, height;
	double heightMargin = 250.0;

	Control control;
	
	JPanel buttonPanel;
	JTextField mergeText;
	JButton mergeButton;
//	JToggleButton resultButton;
	
//	JPanel displayPatternPanel;
	JButton listButton;
	JButton springButton;
	
    JPanel importanceSelectPanel;
    JToggleButton importanceButton[];
	ButtonGroup group;
	
	String inJapanese[];
		
	PopUpForKnowledgeCreation(int X, int Y, int width, int height, Control control)
	{
		super("Knowledge Creation");

		posX = X;
		posY = Y+height/2;		
		
		this.width = width;
		this.height = height;

		this.control = control;
		
		setAlwaysOnTop(true);
		
		inJapanese = FILEIO.TextFileAllReadCodeArray(new File(control.absolutePath+"source"+File.separator+"JapaneseKnowledgeCreation.txt"));		
				
		knowledgeCreationPanel = new KnowledgeCreationPanel();		
		add(knowledgeCreationPanel);
		
		buttonPanel = new JPanel(new GridLayout(3,1));
		buttonPanel.setBackground(Color.YELLOW);
		add(buttonPanel, BorderLayout.SOUTH);
		
		if(control.sp1.inJapanese)
		{
//			resultButton = new JToggleButton(inJapanese[1]);	
			mergeButton = new JButton(inJapanese[2]);
			listButton = new JButton(inJapanese[3]);			
			springButton = new JButton(inJapanese[4]);			
		}
		else
		{
//			resultButton = new JToggleButton("INTERPRETATION");	
			mergeButton = new JButton("MERGE");
			listButton = new JButton("LIST");
			springButton = new JButton("DISTRIBUTION");			
		}
		
        //importance select
        importanceSelectPanel = new JPanel(new GridLayout(1,7));
        
        importanceButton = new JToggleButton[5];
        group = new ButtonGroup();
        
        String label[] = {"ALL","2+","3+","4+","5"};
        
        for(int i=0;i<5;i++)
        {
            importanceButton[i] = new JToggleButton(label[i]);
            importanceButton[i].setOpaque(true);
			importanceButton[i].setBackground(Color.yellow);
            importanceButton[i].addActionListener(this);
            importanceSelectPanel.add(importanceButton[i]);
            group.add(importanceButton[i]);
        }
        importanceButton[0].setSelected(true);
		
		listButton.setOpaque(true);
		springButton.setOpaque(true);
		listButton.setBackground(Color.yellow);
		springButton.setBackground(Color.yellow);
		
		importanceSelectPanel.add(listButton);
		importanceSelectPanel.add(springButton);
		listButton.addActionListener(this);
		springButton.addActionListener(this);		
		
        buttonPanel.add(importanceSelectPanel);
        //
     
		/*
		resultButton.addActionListener(this);		
		buttonPanel.add(resultButton);
		resultButton.setEnabled(false);//After nodes are combined, input interpretations should be saved and results should be revised, too.
						//Because the input interpretation will be vanished when a user pushes this button.
		*/
		 
		mergeText = new JTextField("");
		buttonPanel.add(mergeText);
		
		mergeButton.addActionListener(this);		
		buttonPanel.add(mergeButton);
		/*
		displayPatternPanel = new JPanel(new GridLayout(1,2));
		
		displayPatternPanel.add(listButton);		
		displayPatternPanel.add(springButton);
		buttonPanel.add(displayPatternPanel);
		
		listButton.addActionListener(this);
		springButton.addActionListener(this);		
		*/		


		
		setVisible(true);
		
		this.addWindowListener(new MyWindowListener());			
		
		setBounds(X-100, Y, 1080, height);		
	}
	
	public void subWindowClose()
	{
	
	}
	
	public void quit()
	{
		dispose();
	}
	
	//Action listener
	public void actionPerformed(ActionEvent e)
	{
		for(int i=0;i<5;i++)
			if(e.getSource() == importanceButton[i])
			{
                int importanceThreshold = i+1;
                System.out.println("THRESHOLD: "+importanceThreshold);
//                parent.changeThreshold(importanceThreshold);
                
                knowledgeCreationPanel.changeThreshold(importanceThreshold);
                
                return;
			}
/*        
		if(e.getSource() == resultButton)
		{
			String dataName[] = new String[knowledgeCreationPanel.dataNumber];
			
			if(resultButton.isSelected())
			{
				knowledgeCreationPanel.setResultText(dataName);

				if(control.sp1.inJapanese)
					resultButton.setText(inJapanese[0]);
				else			
					resultButton.setText("RESULT");
			}
			else
			{
				knowledgeCreationPanel.setInterpretationText(dataName);
				
				if(control.sp1.inJapanese)
					resultButton.setText(inJapanese[1]);
				else			
					resultButton.setText("INTERPRETATION");			
			}
			
			knowledgeCreationPanel.network.setNodeWord(dataName);
			knowledgeCreationPanel.repaint();
		}
*/		
		if(e.getSource() == mergeButton)
		{
			if(knowledgeCreationPanel.restDataNumber <= 1)
				return;
			knowledgeCreationPanel.mergeData();
			knowledgeCreationPanel.reArrangeData();
		}
		
		if(e.getSource() == listButton)
		{
			knowledgeCreationPanel.reArrangeData();
			
			knowledgeCreationPanel.linkDisplay = false;			
			knowledgeCreationPanel.repaint();			
		}
		
		if(e.getSource() == springButton)
		{
			knowledgeCreationPanel.network.linkThreshold = 0.0;
			knowledgeCreationPanel.network.createLinksFromValue();				
			knowledgeCreationPanel.network.object[0].x = width;
			knowledgeCreationPanel.network.startSpringModel(width, (int)(height-heightMargin));
			knowledgeCreationPanel.network.linkThreshold = 0.33;
			knowledgeCreationPanel.network.createLinksFromValue();
			
			knowledgeCreationPanel.linkDisplay = true;			
			knowledgeCreationPanel.repaint();
		}		
	}
	
	
	class MyWindowListener extends WindowAdapter {
		
		public void windowClosing(WindowEvent e) // x button
		{
			subWindowClose();
			control.bt78.setSelected(false);			
		}		
		
		public void windowClosed(WindowEvent e) 
		{
			subWindowClose();
			control.bt78.setSelected(false);			
		}
	}
	
///////////////////////	
	
	class KnowledgeCreationPanel extends JPanel implements MouseListener, MouseMotionListener
	{
		DisplayNetwork network;
		int fontSize = 16;
		
		int dataNumber;
		int restDataNumber;
		
		int touchNumber, oldTouchNumber;
		int clickNumber;
		
		boolean selected[];
		
		//For objects operation
		int mouseX, mouseY;			//Coordinates for a mouse
		
		boolean fieldMove;		//Flag for field moving
		int oldMouseX, oldMouseY;	//Last Coordinates for a mosue		

		int mergeTimes = 0;
		int mergedNodeNumber[];
        int importance[];   // 0 if merged
			
		Image smallImage[];
		int imageSize = 50;			
		
		boolean linkDisplay = false;
		
		Color nodeColor[];
		
		KnowledgeCreationPanel()
		{
			addMouseListener(this);			//MouseListener
			addMouseMotionListener(this);	//MouseMotionListener	
			
			nodeColor = new Color[5];
			nodeColor[0] = new Color(0x00,0xbb,0xbb);
			nodeColor[1] = new Color(0x00,0x45,0xff);
			nodeColor[2] = Color.black;//new Color(0x00,0x64,0x00);
			nodeColor[3] = new Color(0xff,0x45,0x00);
			nodeColor[4] = new Color(0xff,0x00,0x00);			
			
			createData();
			
			touchNumber = -1;
			oldTouchNumber = -1;			
		}
		
		void setResultText(String dataName[])
		{
			for(int i=0;i<control.interpretationNumber;i++)
				dataName[i] = control.interpretation[i].result;				
		}
		
		void setInterpretationText(String dataName[])
		{
			for(int i=0;i<control.interpretationNumber;i++)
				dataName[i] = control.interpretation[i].meaning;				
		}		
		
		void createData()
		{

			String dataName[];

			dataNumber = control.interpretationNumber;
			restDataNumber = dataNumber;
			
			dataName = new String[dataNumber];
			setInterpretationText(dataName);		
			network = new DisplayNetwork(dataName, fontSize, Color.black, control.sp1.fontName);
			

			selected = new boolean[dataNumber];

			mergedNodeNumber = new int[dataNumber];
			for(int i=0;i<dataNumber;i++)
				mergedNodeNumber[i] = 0;
            
            importance = new int[dataNumber];
			for(int i=0;i<dataNumber;i++)
				importance[i] = control.interpretation[i].importance;
			
			fontSize = 16;
			
			if(fontSize > (height-heightMargin) / dataNumber)
				fontSize = (int)((height-heightMargin) / dataNumber);
			
			smallImage = new Image[dataNumber];
			
			for(int i=0;i<dataNumber;i++)
			{
				network.object[i].id = i;
				network.object[i].x = 80+i;
				network.object[i].y = (height-heightMargin) / dataNumber * i + 5 + imageSize;

				network.object[i].fontSize = fontSize;
				network.object[i].color = nodeColor[importance[i]-1];
				
				network.object[i].active = true;
				
				selected[i] = false;
				
				smallImage[i] = control.interpretation[i].smallImg;
			}
			
			calculateCosValue();
		}
		
        void changeThreshold(int threshold)
        {
            restDataNumber = 0;
            
            for(int i=0;i<dataNumber;i++)
			{
				selected[i] = false;
                if(importance[i] < threshold)
                    network.object[i].active = false;
                else
                {
                    network.object[i].active = true;
                    restDataNumber++;
                }
			}
            repaint();
        }
        
		void reArrangeData()
		{
			fontSize = 16;
			
			if(fontSize > (height-heightMargin) / restDataNumber)
				fontSize = (int)((height-heightMargin) / restDataNumber);
			
			for(int i=0, count=0;i<dataNumber;i++)
			{
				if(network.object[i].active == true)
				{
					network.object[i].x = 80+count;
					network.object[i].y = (height-heightMargin) / restDataNumber * count + 5 + imageSize;

					network.object[i].fontSize = fontSize + mergedNodeNumber[i];
					network.object[i].color = nodeColor[importance[i]-1];					
					count++;
				}
			}
			calculateCosValue();			
		}	
		
		void calculateCosValue()
		{
			String wordlist[][];
			int wordnum[];
			int coFrequency[][];			
			
			wordlist = new String[dataNumber][100];
			wordnum = new int[dataNumber];
			coFrequency = new int[dataNumber][dataNumber];			

			try{						
				final String dicDir = control.sp1.dictionaryPath+"/ipadic";
				final Tagger tagger = new Tagger(dicDir);
				
				for(int i=0;i<dataNumber;i++)
				{
					wordnum[i] = 0;
					for(Morpheme m : tagger.parse(network.object[i].word))
					{
						String speech[] = m.feature.split(",");
						for(int j=0;j<3;j++)
							if(speech[0].equals(inJapanese[5+j]))
								wordlist[i][wordnum[i]++] = m.surface;
					}
				}
			}
			catch(Exception e){
				System.out.println("writing ERROR in PopUpForKnowledgeCreation.java");
			}			
			
			for(int i=0;i<dataNumber;i++)
				for(int j=0;j<i;j++)
				{
					coFrequency[i][j] = 0;
					
					for(int m=0;m<wordnum[i];m++)
						for(int n=0;n<wordnum[j];n++)
							if(wordlist[i][m].equals(wordlist[j][n]))
								coFrequency[i][j]++;								
				}			
			
			for(int i=0;i<dataNumber;i++)
				for(int j=0;j<=i;j++)
					if(wordnum[i] == 0 || wordnum[j] == 0)
					{
						if(i != j)
							network.value[i][j] = network.value[j][i] = 0.0;
						else
							network.value[i][j] = network.value[j][i] = 1.0;
					}
					else
					{
						network.value[i][j] = network.value[j][i] = (double)coFrequency[i][j] / Math.sqrt(wordnum[i] * wordnum[j]);			
					}
			
	
		
		}
		
		void mergeData()
		{
			String mergedWord = "";
			int mergedNumber = -1;
			String logData = "";
			
			for(int i=0;i<dataNumber;i++)
			{
				if(selected[i])
				{
					mergedWord += network.object[i].word;
					logData += "MERGED NODE "+i+" : ("+importance[i]+") "+network.object[i].word+System.getProperty("line.separator");
                    
					if(mergedNumber == -1)
						mergedNumber = i;
					else
					{
						network.object[i].active = false;
						restDataNumber--;
						mergedNodeNumber[mergedNumber]++;

                        if(importance[i] > importance[mergedNumber])
                            importance[mergedNumber] = importance[i];
                        importance[i] = 0;
					}
					
					selected[i] = false;					
				}
			}
			
			if(mergedNumber == -1)
				return;
			
			String inputText = mergeText.getText();
			
			if(!inputText.equals(""))
			{
				network.object[mergedNumber].word = inputText;
				mergeText.setText("");
				logData += "CREATED NODE "+mergedNumber+" : ("+importance[mergedNumber]+") "+inputText+System.getProperty("line.separator");
			}
			else
			{
				network.object[mergedNumber].word = mergedWord;
				logData += "CREATED NODE "+mergedNumber+" : ("+importance[mergedNumber]+") "+mergedWord+System.getProperty("line.separator");
			}
			
//			network.object[mergedNumber].word = mergedWord;			
			repaint();
			

			writeMergeLog(logData);
			
			mergeTimes++;
		}
		
		//SAVE MERGE LOG 
		String mergeLogFilename;    
		public void writeMergeLog(String data)		//notFirstTime: true -> create new file, false -> add data
		{
			mergeLogFilename = control.absolutePath+"MERGELOG";
			try
			{
				BufferedWriter bw1 = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(mergeLogFilename, mergeTimes!=0), "Shift_JIS"));
				
				bw1.write(String.format(data+System.getProperty("line.separator")));
				bw1.close();
			}
			catch(Exception e){
				System.out.println("File Writing ERROR MERGELOG in Pop up for knowledge creation");
			}		
		}		
		
		
		
		public void drawTouchedData(Graphics2D g2)
		{			
			g2.setColor(Color.green);
			network.fillOval(g2, touchNumber);
			
			g2.setColor(Color.red);
			network.drawOval(g2, touchNumber);
			
			g2.setFont(new Font(control.sp1.fontName, Font.BOLD, network.object[touchNumber].fontSize));
			network.drawWord(g2, touchNumber, Color.red);
		}
		
		public void drawClickedData(Graphics2D g2)
		{			
			for(int i=0;i<dataNumber;i++)
			{
				if(selected[i])
				{			
					g2.setColor(Color.white);
					network.fillOval(g2, i);
			
					g2.setColor(Color.blue);
					network.drawOval(g2, i);
				}
			}
		}		
		
		public void paintComponent(Graphics g)
		{        
			Graphics2D g2 = (Graphics2D)g;
			
			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);// Anti aliasing
			g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);			

			drawBackground(g2);	//Set background
			
			drawData(g2);
		}
		
		void drawBackground(Graphics2D g2)
		{
			int sizeX = getWidth();
			int sizeY = getHeight();

			g2.setColor(new Color(0xE0,0xFF,0xFF));	
			g2.fillRect(0,0, sizeX, sizeY);
			
//			g2.setFont(new Font(control.sp1.fontName, Font.BOLD, fontSize));			
			g2.setColor(Color.blue);			
			g2.drawString(dataNumber+"->"+restDataNumber, 5,sizeY-25);
            if(restDataNumber > 0)
                g2.drawString("value = "+(int)(dataNumber/restDataNumber), 5,sizeY-5);
		}		
		
		void drawImage(Graphics2D g2)
		{
			for(int i=0;i<dataNumber;i++)
				if(mergedNodeNumber[i] == 0 && network.object[i].active)
					g2.drawImage(smallImage[i],(int)network.object[i].x - imageSize - network.object[i].fontSize/2,
								 (int)network.object[i].y - imageSize + network.object[i].fontSize/2,imageSize,imageSize,this);			
		}
		
		void drawData(Graphics2D g2)
		{
			if(linkDisplay)
			{
				g2.setColor(Color.gray);
				g2.setStroke(new BasicStroke(0.1f));			
				network.drawLink(g2);////			
			}
			
			drawImage(g2);
			
			g2.setColor(Color.green);
			g2.setStroke(new BasicStroke(1.0f));			
			network.fillOval(g2);
			
			g2.setColor(Color.black);
			network.drawOval(g2);
			
			network.drawWord(g2);
			

			
			if(touchNumber >= 0)
				drawTouchedData(g2);
			
			drawClickedData(g2);
		}			
		
		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 < 0)
			{
				oldMouseX = mouseX;
				oldMouseY = mouseY;
				fieldMove = true;
				return;
			}
		}
		
		public void mouseReleased(MouseEvent me)	//Release
		{
			fieldMove = false;
		}
		
		public void mouseEntered(MouseEvent me){}	//Enter an area
		public void mouseExited(MouseEvent me){}	//Exit an area
		
		public void mouseClicked(MouseEvent me)	//Click
		{
			int clickNumber;
			
			mouseX = me.getX();
			mouseY = me.getY();
			clickNumber = network.getOnMouseObjectAddLeft(mouseX, mouseY);
			
			if(clickNumber >= 0)
			{
				if(network.object[clickNumber].active == false)
					clickNumber = -1;
				else
				{
					selected[clickNumber] = !selected[clickNumber];
					repaint();
				}
			}
		}	
		
		//MouseMotionListener
		public void mouseDragged(MouseEvent me)	//fieldMove
		{
			mouseX = me.getX();
			mouseY = me.getY();
			
			if(touchNumber >= 0)
			{
				if(network.object[touchNumber].active)
				{
					network.moveObjectByMouse(mouseX, mouseY, touchNumber);
					repaint();
				}
			}
			
			if(fieldMove == true)
			{
				network.moveObjects(mouseX - oldMouseX, mouseY - oldMouseY);
				oldMouseX = mouseX;
				oldMouseY = mouseY;
				repaint();
			}
		}
		
		public void mouseMoved(MouseEvent me)
		{
			mouseX = me.getX();
			mouseY = me.getY();
			
			touchNumber = network.getOnMouseObjectAddLeft(mouseX, mouseY);
			
			if(touchNumber >= 0)
			{
				if(network.object[touchNumber].active == false)
					touchNumber = -1;
			}
			
			if(touchNumber != oldTouchNumber)
			{
				if(touchNumber >= 0)
				{					
						;
				}
				
				repaint();
				oldTouchNumber = touchNumber;
			}
		}
		
		
	}		
}
