import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Vector;

import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;

/**
 * @author utz
 */
public class AminoGUI extends JFrame implements ActionListener
{
	private static final Font ENTRYFONT = new Font("Monospaced", Font.PLAIN, 12);
	private static final Font STATUSFONT = new Font("Monospaced", Font.BOLD, 12);
	// Width of the main GUI window
	private static final int WIDTH = 600;
	// Height of the main GUI window
	private static final int HEIGHT = 768;
	private JTextField statusInfoField;
	private JTable aminoTable;
	final static HashMap KYTEDOO = new HashMap();
	private StringBuffer fileBuffer;
	private int filelength;
	File filename = new File("default.csv");

	public AminoGUI()
	{
		super("Kyte-Doolittle Hydropathy Tool");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		constructGUI();
		setSize(new Dimension(WIDTH, HEIGHT));
		setVisible(true);

		KYTEDOO.put(new Character('A'), new Float(1.8));
		KYTEDOO.put(new Character('C'), new Float(2.5));
		KYTEDOO.put(new Character('D'), new Float(-3.5));
		KYTEDOO.put(new Character('E'), new Float(-3.5));
		KYTEDOO.put(new Character('F'), new Float(2.8));
		KYTEDOO.put(new Character('G'), new Float(-0.4));
		KYTEDOO.put(new Character('H'), new Float(-3.2));
		KYTEDOO.put(new Character('I'), new Float(4.5));
		KYTEDOO.put(new Character('K'), new Float(-3.9));
		KYTEDOO.put(new Character('L'), new Float(3.8));
		KYTEDOO.put(new Character('M'), new Float(1.9));
		KYTEDOO.put(new Character('N'), new Float(-3.5));
		KYTEDOO.put(new Character('P'), new Float(-1.6));
		KYTEDOO.put(new Character('Q'), new Float(-3.5));
		KYTEDOO.put(new Character('R'), new Float(-4.5));
		KYTEDOO.put(new Character('S'), new Float(-0.8));
		KYTEDOO.put(new Character('T'), new Float(-0.7));
		KYTEDOO.put(new Character('V'), new Float(4.2));
		KYTEDOO.put(new Character('W'), new Float(-0.9));
		KYTEDOO.put(new Character('Y'), new Float(-1.3));
	}

	/** 
	 *
	 */
	private void constructGUI()
	{
		Container content = this.getContentPane();
		content.setLayout(new BorderLayout());

		JMenuBar menuBar = new JMenuBar();
		setJMenuBar(menuBar);

		// Menubar Item File is created, accelerator F [Alt + f]
		JMenu file = new JMenu("File");
		file.setMnemonic(KeyEvent.VK_F);

		// Menubar File component open command added to menubar
		JMenuItem item;

		file.add(item = new JMenuItem("Open"));
		// Menuselection Open is created, accelerator O [Alt + o]
		item.setMnemonic(KeyEvent.VK_O);
		item.setActionCommand("Open");
		item.addActionListener(this);

		file.add(item = new JMenuItem("Save"));
		// Menuselection Open is created, accelerator S [Alt + s]
		item.setMnemonic(KeyEvent.VK_S);
		item.setActionCommand("Save");
		item.addActionListener(this);

		file.add(item = new JMenuItem("Exit"));
		//Menuselection Exit is created, accelerator E [Alt + e]
		item.setMnemonic(KeyEvent.VK_E);
		item.setActionCommand("Exit");
		item.addActionListener(this);

		menuBar.add(file);

		// StatusInfoBar is added
		statusInfoField = new JTextField("");
		statusInfoField.setToolTipText("information about current operation");
		statusInfoField.setFont(STATUSFONT);
		statusInfoField.setEditable(false);
		statusInfoField.setBackground(Color.lightGray);
		content.add(statusInfoField, BorderLayout.SOUTH);

		// AminoTable is added

		// Create the scroll pane and add the table to it.
		aminoTable = new JTable();
		aminoTable.setModel(new DefaultTableModel());
		JScrollPane scrollPane = new JScrollPane(aminoTable);

		content.add(scrollPane, BorderLayout.CENTER);
	}

	public void actionPerformed(ActionEvent e)
	{
		boolean status = false;
		String command = e.getActionCommand();
		if (command.equals("Exit"))
		{
			System.exit(0);
		}
		else if (command.equals("Save"))
		{
			// Save a file
			status = saveFile();
			if (!status)
			{
				JOptionPane.showMessageDialog(
					null,
					"IO error in saving file!!",
					"File Save Error",
					JOptionPane.ERROR_MESSAGE);
				statusInfoField.setText(filename + " not saved due to errors!");
			}
			else
			{
				statusInfoField.setText(filename + " saved successfully");
			}
		}

		else if (command.equals("Open"))
		{

			File fastaFile = openFastaFile();

			if (fastaFile == null)
			{
				return;
			}

			String s = JOptionPane.showInputDialog(this, "Enter windowsize");
			int windowsize = Integer.parseInt(s);

			StringBuffer protein_sequence = new StringBuffer();
			try
			{
				BufferedReader in = new BufferedReader(new FileReader(fastaFile));

				String line;

				while ((line = in.readLine()) != null)
				{
					filelength = line.length();
					if (line.length() > 0)
					{
						if (line.charAt(0) == '>')
						{
							if (protein_sequence.length() > 0)
							{
								break;
							}
						}
						else
						{
							for (int i = 0; i < line.length(); i++)
							{
								char seq_char = line.charAt(i);
								if (Character.isLetter(seq_char))
								{
									protein_sequence.append(seq_char);
								}
							}
						}
					}
				}
				in.close();
			}
			catch (Exception ex)
			{
				ex.printStackTrace();
				protein_sequence = new StringBuffer();
			}

			double[] scorearray = new double[protein_sequence.length()];
			for (int i = 0; i < protein_sequence.length(); i++)
			{
				Character seq_char = new Character(protein_sequence.charAt(i));
				try
				{
					scorearray[i] = ((Float) KYTEDOO.get(seq_char)).floatValue();
				}
				catch (Exception e1)
				{
					scorearray[i] = 0.0;
				}
			}

			DecimalFormat score_format = new DecimalFormat("0.0");
			Vector rowData = new Vector();
			Vector tableData = new Vector();
			fileBuffer = new StringBuffer();

			for (int i = 0; i < protein_sequence.length(); i++)
			{
				//add index
				rowData.add((i + 1) + "");
				char amino = protein_sequence.charAt(i);
				//add Amino Letter
				rowData.add(new Character(amino));
				// add windowscore
				double windowscore = 0.0;
				int windowhalf = windowsize / 2;
				int startwindow = i - windowhalf;
				int stopwindow = i + windowhalf;

				for (int k = Math.max(0, startwindow);
					k <= Math.min(stopwindow, (protein_sequence.length() - 1));
					k++)
				{
					windowscore += scorearray[k];
				}

				rowData.add(score_format.format(windowscore));
				fileBuffer.append(
					(i + 1) + "\t" + amino + "\t" + score_format.format(windowscore) + "\n");
				tableData.add(rowData);
				rowData = new Vector();
			}

			rowData = new Vector();
			rowData.add("Index");
			rowData.add("One letter code");
			rowData.add("Score");
			DefaultTableModel model = new DefaultTableModel(tableData, rowData);
			aminoTable.setModel(model);

		}
	}

	public File openFastaFile()
	{
		JFileChooser fc = new JFileChooser(".");
		if (fc.showOpenDialog(this) != JFileChooser.APPROVE_OPTION)
		{
			return null;
		}
		return fc.getSelectedFile();
	}
	boolean saveFile()
	{
		File file = null;
		JFileChooser fc = new JFileChooser();
		// Start in current directory
		fc.setCurrentDirectory(new File("."));
		// Set to a default name for save.
		fc.setSelectedFile(filename);
		// Open chooser dialog
		int result = fc.showSaveDialog(this);
		if (result == JFileChooser.CANCEL_OPTION)
		{
			return true;
		}
		else if (result == JFileChooser.APPROVE_OPTION)
		{
			file = fc.getSelectedFile();
			if (file.exists())
			{
				int response =
					JOptionPane.showConfirmDialog(
						null,
						"Overwrite existing file?",
						"Confirm Overwrite",
						JOptionPane.OK_CANCEL_OPTION,
						JOptionPane.QUESTION_MESSAGE);
				if (response == JOptionPane.CANCEL_OPTION)
					return false;
			}
			String text = fileBuffer.toString();
			return writeFile(file, text);
		}
		else
		{
			return false;
		}
	}
	public static boolean writeFile(File file, String dataString)
	{

		try
		{
			PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(file)));
			out.print(dataString);
			out.flush();
			out.close();
		}
		catch (IOException e)
		{
			return false;
		}
		return true;
	}

	public static void main(String[] args)
	{
		new AminoGUI();
	}
}