package interfaces;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;

import analyzer.Backpropagation.NeuralDenormalizer;
import analyzer.Constants;
import analyzer.FeedForward;
import analyzer.StructureReader;

public class TestGUInterface extends JFrame {

	private JPanel contentPane;
	private JTextField textFieldDate;
	private JTextField textFieldResult;
	private JButton btnStartTesting;
	private JLabel lblStatus;
	private JFrame frame;

	private String defaultChooserDirectory;

	private FeedForward feedForward;
	private StructureReader structureReader;

	private float[][] mWeightH, mWeightO;

	/**
	 * Launch the application.
	 */
	// public static void main(String[] args) {
	// EventQueue.invokeLater(new Runnable() {
	// public void run() {
	// try {
	// TestGUInterface frame = new TestGUInterface();
	// frame.setVisible(true);
	// } catch (Exception e) {
	// e.printStackTrace();
	// }
	// }
	// });
	// }

	/**
	 * Create the frame.
	 */
	public TestGUInterface() {
		defaultChooserDirectory = System.getProperty("user.dir");
		frame = this;
		setResizable(false);
		setTitle("Neural Network Test Phase");
		setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
		addWindowListener(new java.awt.event.WindowAdapter() {
			@Override
			public void windowClosing(java.awt.event.WindowEvent windowEvent) {
				if (JOptionPane.showConfirmDialog(frame, "Close this window?", "Confirm ?", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) {
					new MainGUInterface().setVisible(true);
					frame.dispose();
				}
			}
		});
		setBounds(100, 100, 450, 251);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(null);

		JLabel lblEnterDate = new JLabel("Enter date:");
		lblEnterDate.setBounds(10, 47, 88, 14);
		contentPane.add(lblEnterDate);

		JButton btnSelectStructure = new JButton("Select Structure");
		btnSelectStructure.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent arg0) {
				JFileChooser fileChooser = new JFileChooser(defaultChooserDirectory);
				if (fileChooser.showOpenDialog(frame) == JFileChooser.APPROVE_OPTION) {
					File file = fileChooser.getSelectedFile();
					structureReader = new StructureReader(file.getPath());

					try {
						defaultChooserDirectory = file.getCanonicalPath();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					if (!structureReader.isCorrectStructure()) {
						//JOptionPane.showMessageDialog(frame, "Invalid file structure.", "Format error", JOptionPane.INFORMATION_MESSAGE);
						return;
					}

					mWeightH = structureReader.getWeightH();
					mWeightO = structureReader.getWeightO();
					lblStatus.setText("Status: Ready (" + file.getName() + ")");
					btnStartTesting.setEnabled(true);
				}

			}
		});

		btnSelectStructure.setBounds(10, 11, 143, 23);
		contentPane.add(btnSelectStructure);

		textFieldDate = new JTextField();
		textFieldDate.setBounds(94, 44, 143, 20);
		contentPane.add(textFieldDate);
		textFieldDate.setColumns(10);

		Date date = new Date();
		DateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy");
		textFieldDate.setText(dateFormat.format(date));

		btnStartTesting = new JButton("Start Testing");
		btnStartTesting.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent arg0) {
				String date = textFieldDate.getText();
				String[] input = date.split("\\.");
				if (input.length != 3) {
					JOptionPane.showMessageDialog(frame, "Invalid date format.", "Format error", JOptionPane.INFORMATION_MESSAGE);

					return;
				}

				float[] in = new float[input.length];
				for (int i = 0; i < input.length; i++) {
					in[i] = Float.parseFloat(input[i]);
					if (i == 0 && in[i] > 31) {
						JOptionPane.showMessageDialog(frame, "Enter day between 1~31.", "Date Error", JOptionPane.INFORMATION_MESSAGE);
						return;
					} else if (i == 1 && in[i] > 12) {
						JOptionPane.showMessageDialog(frame, "Enter month between 1~12.", "Date Error", JOptionPane.INFORMATION_MESSAGE);
						return;
					}
					// else if (i == 2 && (in[i] > 10000 || in[i] < 1900)) {
					// JOptionPane.showMessageDialog(frame, "Enter year between 1900~3000.", "Date Error", JOptionPane.INFORMATION_MESSAGE);
					// return;
					// }
				}
				System.out.println();

				feedForward = new FeedForward(in, mWeightH, mWeightO, true);
				feedForward.applyFeedForward();
				float[] output = feedForward.getNetOutputO();
				// for (int i = 0; i < output.length; i++)
				// System.out.print(output[i] + " ");
				// System.out.println();
				String formattedOutput = getFormattedOutPut(output);
				textFieldResult.setText(formattedOutput);
			}
		});
		btnStartTesting.setEnabled(false);
		btnStartTesting.setBounds(10, 117, 143, 23);
		contentPane.add(btnStartTesting);

		JLabel lblExpectedLotteryNumbers = new JLabel("Expected Lottery Numbers: ");
		lblExpectedLotteryNumbers.setBounds(10, 155, 157, 14);
		contentPane.add(lblExpectedLotteryNumbers);

		textFieldResult = new JTextField();
		textFieldResult.setEditable(false);
		textFieldResult.setBounds(175, 152, 143, 20);
		contentPane.add(textFieldResult);
		textFieldResult.setColumns(10);

		lblStatus = new JLabel("Status: No Structure Loaded");
		lblStatus.setBounds(10, 188, 414, 14);
		contentPane.add(lblStatus);
	}

	public static String getFormattedOutPut(float[] output) {
		String formattedOutput = "";
		for (int i = 0; i < output.length; i++) {
			long gen = (long) (10000 * output[i]); // Extracting denormalize factor
			NeuralDenormalizer scaler = new NeuralDenormalizer(gen);
			int scaledOutput = scaler.scale(Constants.MAX - Constants.MIN) + Constants.MIN;
			formattedOutput += scaledOutput;
			if (output.length - i != 1)
				formattedOutput += " , ";
		}
		return formattedOutput;
	}
}
