package gui;

import gui.settings.SettingsController;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.border.Border;

import logging.Log;
import logging.LogLevel;

/**
 * Main Frame of application (view of MVC-Pattern)
 * 
 * @author Martin Pabst, 2009
 * 
 */
public class MainFrame extends JFrame implements ActionListener {

	private static MainFrame instance = null;

	/**
	 * Button "Skript starten"
	 */
	private JButton buttonStartScript;

	/**
	 * Button "Datumsangaben ändern"
	 */
	private JButton buttonChangeDates;

	/**
	 * Button "Test"
	 */
	private JButton buttonCorrectFitnesseScripts;

	/**
	 * button to edit settings
	 */
	private JButton buttonEditSettings;

	/**
	 * button to edit settings
	 */
	private JButton buttonOutputDateFields;

	/**
	 * button to edit database settings
	 */
	private JButton buttonEditDatabaseSettings;

	/**
	 * Controller for this window (MVC-Pattern!)
	 */
	private MainFrameController controller;
	/**
	 * Textarea for log-output
	 */
	private ColorPane textArea;
	/**
	 * Textarea and progressbar are positioned on a splitpane, so that
	 * progressbar can be made invisible
	 */
	private JSplitPane splitPane;
	/**
	 * progressbar
	 */
	private JProgressBar progressBar;

	/**
	 * Array containing all LogLevels. Used for configuring radiobuttons
	 */
	private LogLevel[] LogLevels = { LogLevel.trace, LogLevel.info,
			LogLevel.useful, LogLevel.warning, LogLevel.error };

	/**
	 * Radiobuttons for choosing loglevel
	 */
	private JRadioButton logLevelButtons[] = new JRadioButton[LogLevels.length];

	/**
	 * returns textarea for log-output
	 * 
	 * @return
	 */
	public ColorPane getTextArea() {
		return textArea;
	}

	/**
	 * Singleton-Pattern.
	 * 
	 * @return one and only istance of this object
	 */
	public static MainFrame getInstance() {
		if (instance == null) {
			instance = new MainFrame();
		}
		return instance;
	}

	/**
	 * set controller for this mainframe (mvc-pattern)
	 * 
	 * @param controller
	 */
	public void setController(MainFrameController controller) {
		this.controller = controller;
	}

	/**
	 * contructor; needs reference to controller (MVC-Pattern)
	 * 
	 * @param controller
	 */
	private MainFrame() {

	}

	/**
	 * init GUI
	 */
	public void init() {
		/*
		 * 16x16 window-icon
		 */
		setIconImage(Toolkit.getDefaultToolkit().getImage("data/script_go.png"));

		setSize(800, 750);

		setTitle("ASV-Zeitmaschine (M.Pabst, 09.09.2010)");

		/*
		 * main panel fits into whole content section of window
		 */
		JPanel mainPanel = new JPanel();
		mainPanel.setLayout(new BorderLayout());

		/*
		 * register main panel
		 */
		getContentPane().setLayout(new BorderLayout());
		getContentPane().add(mainPanel, BorderLayout.CENTER);

		/*
		 * north panel holds butons and radiobutton section for
		 * loglevel-choosing
		 */
		JPanel northPanel = new JPanel();
		northPanel.setLayout(new BorderLayout());
		northPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));

		/*
		 * buttonpanel holds buttons
		 */
		JPanel buttonPanel = new JPanel();

		buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.Y_AXIS));
		mainPanel.add(northPanel, BorderLayout.NORTH);

		/**
		 * setup buttons
		 */
		buttonStartScript = new JButton("Skripts starten");
		buttonStartScript.addActionListener(this);
		buttonPanel.add(buttonStartScript);

		buttonPanel.add(Box.createRigidArea(new Dimension(0, 10)));

		buttonChangeDates = new JButton("Datumsangaben ändern");
		buttonChangeDates.addActionListener(this);
		buttonPanel.add(buttonChangeDates);

		buttonPanel.add(Box.createRigidArea(new Dimension(0, 10)));

		buttonCorrectFitnesseScripts = new JButton(
				"Fitnesse-Scripts korrigieren");
		buttonCorrectFitnesseScripts.addActionListener(this);
		buttonPanel.add(buttonCorrectFitnesseScripts);

		buttonPanel.add(Box.createRigidArea(new Dimension(0, 10)));

		buttonEditSettings = new JButton("Einstellungen bearbeiten");
		buttonEditSettings.addActionListener(this);
		buttonPanel.add(buttonEditSettings);

		buttonPanel.add(Box.createRigidArea(new Dimension(0, 10)));

		buttonOutputDateFields = new JButton("Datumsfelder ausgeben");
		buttonOutputDateFields.addActionListener(this);
		buttonPanel.add(buttonOutputDateFields);

		buttonPanel.add(Box.createRigidArea(new Dimension(0, 10)));

		buttonEditDatabaseSettings = new JButton(
				"Datenbankverbindung einstellen...");
		buttonEditDatabaseSettings.addActionListener(this);
		buttonPanel.add(buttonEditDatabaseSettings);

		/*
		 * radiopanel for choosing loglevel
		 */
		JPanel radioButtonPanel = new JPanel();
		radioButtonPanel.setLayout(new BoxLayout(radioButtonPanel,
				BoxLayout.Y_AXIS));
		Border blackline = BorderFactory.createLineBorder(Color.black);
		radioButtonPanel.setBorder(BorderFactory.createTitledBorder(blackline,
				"Logging:"));

		ButtonGroup bg = new ButtonGroup();

		for (int i = 0; i < LogLevels.length; i++) {
			LogLevel logLevel = LogLevels[i];
			JRadioButton rb = new JRadioButton(logLevel.name());
			logLevelButtons[i] = rb;
			if (logLevel == LogLevel.info) {
				rb.setSelected(true);
				Log.setMinimumLogLevel(LogLevel.info);
			}
			bg.add(rb);
			rb.addActionListener(this);
			radioButtonPanel.add(rb);
		}

		buttonPanel.add(Box.createRigidArea(new Dimension(0, 20)));

		northPanel.add(radioButtonPanel, BorderLayout.EAST);
		northPanel.add(buttonPanel, BorderLayout.CENTER);

		buttonPanel.add(Box.createHorizontalGlue());
		buttonPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));

		/*
		 * centerPanel holds textarea
		 */
		JPanel centerPanel = new JPanel();
		centerPanel.setLayout(new BorderLayout());

		textArea = new ColorPane();
		JScrollPane scrollPane = new JScrollPane(textArea);
		centerPanel.add(scrollPane, BorderLayout.CENTER);

		JPanel progressBarPanel = new JPanel();
		progressBarPanel.setLayout(new BorderLayout());

		progressBar = new JProgressBar();
		progressBarPanel.add(progressBar);

		/*
		 * splitpane holds progressbar and textarea
		 */
		splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true,
				progressBarPanel, centerPanel);
		splitPane.setDividerSize(0);
		enableProgressBar(false);

		mainPanel.add(splitPane, BorderLayout.CENTER);

		setButtonsEnabled(true);

		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

	}

	/**
	 * enable/disable progressbar. Progressbar is invisible when disabled.
	 * 
	 * @param enabled
	 */
	public void enableProgressBar(boolean enabled) {
		if (enabled) {
			progressBar.setStringPainted(true);
			splitPane.setDividerLocation(20);
		} else {
			splitPane.setDividerLocation(0);
		}
	}

	/**
	 * set maximum value of progressbar. max == -1 sets indefinite mode
	 * 
	 * @param max
	 */
	public void setProgressBarMaximum(int max) {
		if (max >= 0) {
			progressBar.setMaximum(max);
			progressBar.setIndeterminate(false);
		} else {
			progressBar.setIndeterminate(true);
		}
		progressBar.setString("");
	}

	/**
	 * set position of progressbar.
	 * 
	 * @param value
	 * @param text
	 */
	public void setProgressBarPosition(int value, String text) {
		progressBar.setValue(value);
		progressBar.setString(text);
	}

	/**
	 * delegator or button- and radiobutton-action
	 */
	@Override
	public void actionPerformed(ActionEvent e) {

		/**
		 * Start user-defined sql script (script is stored in file
		 * settings.xml!)
		 */

		if (e.getSource() == buttonStartScript) {
			controller.startScript();
		}

		/**
		 * change dates in database
		 */

		if (e.getSource() == buttonChangeDates) {
			controller.changeDates();
		}

		/**
		 * change dates in database
		 */

		if (e.getSource() == buttonCorrectFitnesseScripts) {
			controller.correctFitnesseScripts();
		}

		/**
		 * button 'edit settings' pressed
		 */
		if (e.getSource() == buttonEditSettings) {
			EditSettingsDialog esd = new EditSettingsDialog(this, true);
			esd.setVisible(true);
			controller.readSettings();
		}

		/**
		 * button 'edit settings' pressed
		 */
		if (e.getSource() == buttonOutputDateFields) {
			controller.outputDateFields();
		}

		/**
		 * button 'edit settings' pressed
		 */
		if (e.getSource() == buttonEditDatabaseSettings) {
			SettingsController sc = new SettingsController();

			// EditSettingsDialog esd = new EditSettingsDialog(this, true);
			// esd.setVisible(true);

			if (!sc.isExitCancel()) {
				controller.clearTextArea();
				controller.readSettings();
			}

		}

		/**
		 * radiobutton with loglevel-setting pressed
		 */
		for (int i = 0; i < logLevelButtons.length; i++) {
			if (e.getSource() == logLevelButtons[i]) {
				Log.setMinimumLogLevel(LogLevels[i]);
			}
		}

	}

	/**
	 * enable buttons.
	 * 
	 * @param enabled
	 */
	public void setButtonsEnabled(boolean enabled) {
		buttonStartScript.setEnabled(enabled);
		buttonChangeDates.setEnabled(enabled);
	}

	/**
	 * If isWait == true then set waitcursor, else set default cursor.
	 * 
	 * @param isWait
	 */
	public void setWaitCursor(boolean isWait) {

		if (isWait) {
			setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
			textArea.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
		} else {
			setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
			textArea.setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR));
		}
	}

}
