/*
 * MainWindow.java
 *
 * Created on Ketvirtadienis, 2007, Sausio 25, 17.00
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package Main;

import java.security.*;
import Main.parser.*;
import javax.swing.table.*;
import Main.data.*;
import java.awt.datatransfer.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;
import Main.algorithms.*;

import java.applet.*;
import java.awt.*;
import javax.swing.*;
import java.util.*;

import Main.panels.*;

public class MainWindow extends JFrame
{
	private int appWidth;
	private int appHeight;
	private JTabbedPane mTabbedPane;
	private MainPanel mMainPanel;
	private DataPanel mInputDataPanel;
	private RezultsPanel mRezultsPanel;
	private RezultsComparingPanel mRezultsComparingPanel;
	private OutputStreamPanel mOutputStreamPanel;
	private AlgorithmPanel mAlgorithmPanel;
	private static MainWindow mInstance;
	private AbstractAlgorithm mAlgorithm;
	
	private Clipboard mSystemClipboard;
	
	private URL mCodeBase= null;
	
	public static final String ENVIRONMENT_FILE= "environment.txt";
	private final String DATA_LOAD_URL= "DATA_LOAD_URL";
	private final String DATA_SAVE_URL= "DATA_SAVE_URL";
	private final String RESULTS_SAVE_URL= "RESULTS_SAVE_URL";
	
	private final String U_EQUTION= "U_EQUTION";
	private final String V_EQUTION= "V_EQUTION";
	
	private final String VARIABLES= "VARIABLES";
	
	
	private MainWindow()
	{
		super();
		init();
		setSize(getPreferredSize());
		addWindowListener(new WindowAdapter()
		{
			public void windowClosing(WindowEvent e) 
			{
				saveEnvironment();
			}
			
			public void windowOpened(WindowEvent e)
			{
				loadEnvironment();
			}
		}
		);
		
		
	}
	
	static public void main(String arg[])
	{
		//System.setErr(new Main.util.OutputStream());
		//System.setOut(new Main.util.OutputStream());
		MainWindow mw= MainWindow.getInstance();
		mw.pack();
		(mw).setVisible(true);
		MainWindow.getInstance().setAlgorithm(new DSAAlgorithm());
		
	}
	
	public void init()
	{
		//new MainWindow();
		//appWidth = getSize().width;
		//appHeight = getSize().height;
	
		mTabbedPane= new JTabbedPane();
		getContentPane().setLayout(new BorderLayout());
		
				
		getContentPane().add(mTabbedPane, BorderLayout.CENTER);
		mMainPanel= new MainPanel();
		mInputDataPanel= new DataPanel();
		mRezultsPanel= new RezultsPanel();
		mRezultsComparingPanel= new RezultsComparingPanel();
		mOutputStreamPanel= new OutputStreamPanel();
		mAlgorithmPanel= new AlgorithmPanel();
		mTabbedPane.addTab("Main", mMainPanel);
		mTabbedPane.addTab("Input Data", mInputDataPanel);
		mTabbedPane.addTab("Output Data", mRezultsPanel);
		//mTabbedPane.addTab("Evaluation Data", mRezultsComparingPanel);
		mTabbedPane.addTab("Output", mOutputStreamPanel);
		mTabbedPane.addTab("( U,V ) Specification",mAlgorithmPanel);
		
		boolean canAccessClipboard= true;
		
		try{
			mSystemClipboard= Toolkit.getDefaultToolkit().getSystemClipboard();
		}
		catch(SecurityException e)
		{
			canAccessClipboard= false;
			System.err.println( "MESSAGE: "+e.getMessage() );
			MainPanel.showInfo("Access to clipboard is denied");
		}
	
		
		mTabbedPane.addKeyListener(new KeyAdapter()
		{
			public void keyPressed(KeyEvent e)
			{
				keyPressedAction(e);
			}
		}
		);
	
		AbstractAlgorithm.setLog( getOutputStreamPanel() );
				
	}
	
	public static MainWindow getInstance()
	{
		if(mInstance == null)
		{
			mInstance= new MainWindow();
		}
		return mInstance;
	}
	
	public java.util.List getInputData()
	{
		return mInputDataPanel.getInputData();
	}
	
	public DataPanel getInputDataPanel()
	{
		return mInputDataPanel;
	}
	
	public RezultsPanel getOutputDataPanel()
	{
		return mRezultsPanel;
	}
	
	public OutputStreamPanel getOutputStreamPanel()
	{
		return mOutputStreamPanel;
	}
	
	public RezultsComparingPanel getRezultsComparingPanel()
	{
		return mRezultsComparingPanel;
	}
	
	public void setAlgorithm(AbstractAlgorithm alg)
	{
		mAlgorithm= alg;
	}
	
	public AbstractAlgorithm getAlgorithm()
	{
		return mAlgorithm;
	}
	
	public void setCodeBase(URL codeBase)
	{
		mCodeBase= codeBase;
	}
	
	public URL getCodeBase()
	{
		return mCodeBase;
	}
	
	private void keyPressedAction(KeyEvent e)
	{
		if(e.getKeyCode() == KeyEvent.VK_C && e.isControlDown())
		{
			// on data copy
			if(mTabbedPane.getSelectedComponent() == mInputDataPanel)
			{
				copyData();
			}
			else if( mTabbedPane.getSelectedComponent() == mRezultsPanel )
			{
				copyRezult();
			}
			else if( mTabbedPane.getSelectedComponent() == mRezultsComparingPanel )
			{
				copyComparingRezult();
			}
			
		}
		else if(e.getKeyCode() == KeyEvent.VK_V && e.isControlDown())
		{
			if(mTabbedPane.getSelectedComponent() == mInputDataPanel)
			{
				pasteData();
			}
		}
	}
	
	private void copyData()
	{
		StringBuffer buffer= new StringBuffer();
		java.util.List v= mInputDataPanel.getInputData();
		buffer.append(InputDataSlot.createRepresentationString()+"\n");
		if(v!= null)
		{
			for(Iterator it= v.iterator();it.hasNext();)
			{
				InputDataSlot slot= (InputDataSlot)it.next();
				buffer.append( slot.createDataString()+"\n");
			}
		}
		
		StringSelection selection= new StringSelection(new String(buffer));
		mSystemClipboard.setContents(selection, selection);
	}
	
	private void copyRezult()
	{
		StringBuffer buffer= new StringBuffer();
		java.util.List v= mRezultsPanel.getOutputModel().getData();
		if(v!= null)
		{
			for(Iterator it= v.iterator();it.hasNext();)
			{
				OutputDataSlotXY slot= (OutputDataSlotXY)it.next();
				buffer.append( slot.getX()+" "+slot.getY()+'\n');
			}
		}
		
		StringSelection selection= new StringSelection(new String(buffer));
		mSystemClipboard.setContents(selection, selection);
	}
	
	private void copyComparingRezult()
	{
		StringBuffer buffer= new StringBuffer();
		java.util.Vector v= ((DefaultTableModel)mRezultsComparingPanel.getModel()).getDataVector();
		if(v!= null)
		{
			for(Iterator it= v.iterator();it.hasNext();)
			{
				Vector slot= (Vector)it.next();
				buffer.append( slot.get(1).toString()+' '+slot.get(2).toString()+' '+slot.get(3).toString()+' '+slot.get(4).toString()+'\n');
			}
		}
		
		StringSelection selection= new StringSelection(new String(buffer));
		mSystemClipboard.setContents(selection, selection);
	}
	
	private void pasteData()
    {
		Transferable trans= mSystemClipboard.getContents(null);
		String data= null;
		try{
		if(trans.isDataFlavorSupported(DataFlavor.plainTextFlavor) )
		{
			StringReader reader= (StringReader)trans.getTransferData( DataFlavor.plainTextFlavor);
			int c;
			StringBuffer buffer= new StringBuffer(); 
			while((c= reader.read())!= -1)
			{
				buffer.append((char)c);
			}
			data= new String(buffer);
		}
		else if(trans.isDataFlavorSupported(DataFlavor.stringFlavor))
		{
			data= (String)trans.getTransferData( DataFlavor.stringFlavor);
		}
		
		if(data != null)
		{
			ByteArrayInputStream str= new ByteArrayInputStream(data.getBytes());
			java.util.List list= readData(str);
			mInputDataPanel.getInputDataModel().setColumns(InputDataSlot.DATA_NAMES);
			mInputDataPanel.getInputDataModel().setData( list);
		}
		}
		catch(UnsupportedFlavorException e)
		{
		}
		catch(IOException e)
		{
		}
	}
	
	/**
	*  Reads plain data - no header checked
	*/
	public java.util.List readData(InputStream str)
	{
		DataInputStream stream= new DataInputStream(str);
		java.util.List list= new ArrayList();
		java.util.List stringList= new ArrayList();
		String line= null;
		String[] names= InputDataSlot.DATA_NAMES_CONST;
		try
		{
			// first line is pattern P G Q
			line= stream.readLine();
			StringTokenizer tokenizer= new StringTokenizer(line);
			names= new String[tokenizer.countTokens()];
			for(int i= 0;tokenizer.hasMoreTokens(); i++)
			{
				names[i]= tokenizer.nextToken();
			}
		}
		catch(IOException e)
		{
			e.printStackTrace();
		}
		
		while(true)
		{
			line= null;
			try{
				line= stream.readLine();
				if(line == null)
					break;
				StringTokenizer tokenizer= new StringTokenizer(line);
				for(;tokenizer.hasMoreTokens();)
				{
					stringList.add( tokenizer.nextToken() );
					
				}
			}
			catch(IOException e)
			{
				break;
			}
			
		}
		
		InputDataSlot.DATA_NAMES= names;
		
		for(Iterator it= stringList.iterator();it.hasNext();)
		{
			
			float[] data= new float[names.length];
			int i= 0;
			while(it.hasNext() && i< data.length )
			{
				String s= (String)it.next();
				try{
					data[i]= Float.parseFloat(s);
				}
				catch(NumberFormatException e)
				{
				}
				i++;
			}
			// if readed fully
			if(i==data.length)
			{
				list.add(new InputDataSlot(data) );
			}
			
		}
		
		
		return list;
	}
	
	public void saveEnvironment()
	{
		//System.err.println( "SAVING ENVIRONMENT"+getCodeBase());
		
		Properties prop= new Properties();
		prop.put(DATA_LOAD_URL,mMainPanel.getDataLoadURL());
		prop.put(DATA_SAVE_URL,mMainPanel.getDataSaveURL());
		prop.put(RESULTS_SAVE_URL,mMainPanel.getResultsSaveURL());
		
		prop.put(U_EQUTION, mAlgorithmPanel.getUEquation());
		prop.put(V_EQUTION, mAlgorithmPanel.getVEquation());
		
		StringBuffer buffer= new StringBuffer(); 
		for(int i= 0; i< InputDataSlot.DATA_NAMES.length; i++)
		{
			buffer.append(InputDataSlot.DATA_NAMES[i]).append(" ");
		}
		prop.put(VARIABLES, new String(buffer));
		File file;
		
		if(getCodeBase() != null)
		{
			/*URL url= null;
			try{
				url= new URL(getCodeBase(), ENVIRONMENT_FILE);
			}
			catch(MalformedURLException e)
			{
				System.err.println("Environment can't be saved!. Error: "+e.getMessage());
				e.printStackTrace();
				return;
			}
			
			file= new File(url.getFile());*/
			file= new File(getCodeBase().getFile());
		}
		else
		{
			file= new File(ENVIRONMENT_FILE);
		}
		
		try{
			FileOutputStream out= new FileOutputStream(file);
			prop.save(out, null);
			out.close();
		}
		catch(Exception e)
		{
			System.err.println("Environment can't be saved!. Error: "+e.getMessage());
			e.printStackTrace();
		}
	}
	
	public void loadEnvironment()
	{
		//System.err.println( "LOADING ENVIRONMENT: "+getCodeBase());
		Properties prop= new Properties();
		
		File file;

		if(getCodeBase() != null)
		{
			/*URL url= null;
			try{
				url= new URL(getCodeBase(), ENVIRONMENT_FILE);
			}
			catch(MalformedURLException e)
			{
				System.err.println("Environment can't be loaded!. Error: "+e.getMessage());
				return;
			}
			file= new File(url.getFile());*/
			file= new File(getCodeBase().getFile());
			//System.err.println("FILE: "+file.getAbsolutePath());
		}
		else
		{
			file= new File(ENVIRONMENT_FILE);
		}
		
		/*Permission permission;
		permission= new FilePermission(file.getAbsolutePath(), "read");
		System.getSecurityManager().checkPermission(permission);
		catch(SecurityException e)
		{
		}*/
		
		try{
			FileInputStream in= new FileInputStream(file);
			prop.load(in);
			in.close();
		}
		catch(AccessControlException e)
		{
			MainPanel.showInfo("Access to environment file \"environment.txt\" is denied");
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		
		
		mMainPanel.setDataLoadURL((String)prop.get(DATA_LOAD_URL));
		mMainPanel.setDataSaveURL((String)prop.get(DATA_SAVE_URL));
		mMainPanel.setResultsSaveURL((String)prop.get(RESULTS_SAVE_URL));
		
		mAlgorithmPanel.setUEquation((String)prop.get(U_EQUTION) );
		mAlgorithmPanel.setVEquation((String)prop.get(V_EQUTION));
		
		EquationsManager.getInstance().parseText(mAlgorithmPanel.getUEquation(), EquationsManager.U_EQUATION);
		EquationsManager.getInstance().parseText(mAlgorithmPanel.getVEquation(), EquationsManager.V_EQUATION);
		
		String tmp;
		String[] variables;
		if((tmp= (String)prop.get(VARIABLES))!= null)
		{
			StringTokenizer tok= new StringTokenizer(tmp);
			variables= new String[tok.countTokens()];
			for(int i= 0;tok.hasMoreTokens();i++)
			{
				variables[i]= tok.nextToken();
			}
			InputDataSlot.DATA_NAMES= variables;
			mInputDataPanel.getInputDataModel().setColumns(InputDataSlot.DATA_NAMES);
		}
		
	}
	

}