/**
 * 
 */
package cz.neubauer.tomas.hazardanalysis.viewcontroller.administration;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;

import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;

import cz.neubauer.tomas.hazardanalysis.model.components.Component;
import cz.neubauer.tomas.hazardanalysis.model.components.ComponentCatalog;
import cz.neubauer.tomas.hazardanalysis.model.dangers.DangerGroup;
import cz.neubauer.tomas.hazardanalysis.model.dangers.DangerType;
import cz.neubauer.tomas.hazardanalysis.model.dangers.DangerVariant;
import cz.neubauer.tomas.hazardanalysis.model.tablemodels.ComponentTableModel;
import cz.neubauer.tomas.hazardanalysis.viewcontroller.MainFrame;
import cz.neubauer.tomas.hazardanalysis.viewcontroller.windowmanipulator.WindowManipulator;

/**
 * @author Tomáš Neubauer
 */
public class AdminFrame extends JFrame {

	/**
	 * 
	 */
	private static final long serialVersionUID = -8831256305745180895L;

	private MainFrame owner;

	private JTabbedPane tpnTabs;

	private JPanel pnlComponents, pnlDangers;

	private JTable tblComponents;

	private JTree treDangers;

	private JPopupMenu pmnDangersPopup, pmnComponentsPopup;

	private JMenuItem mniAddDanger, mniDeleteDanger, mniUpdateDanger;

	private JMenuItem mniAddComponent, mniDeleteComponent, mniUpdateComponent;

	private DangerGroupList dangerGroups;

	public AdminFrame(MainFrame owner) {
		this.owner = owner;
		dangerGroups = new DangerGroupList();
		initGUI();
		// setVisible(true);
	}

	/**
	 * 
	 */
	private void initGUI() {
		setDefaultCloseOperation(HIDE_ON_CLOSE);
		setTitle("Správa databáze");

		addWindowListener(new WindowListener() {

			@Override
			public void windowOpened(WindowEvent e) {
				// nop
			}

			@Override
			public void windowIconified(WindowEvent e) {
				// nop
			}

			@Override
			public void windowDeiconified(WindowEvent e) {
				// nop
			}

			@Override
			public void windowDeactivated(WindowEvent e) {
				// nop
			}

			@Override
			public void windowClosing(WindowEvent e) {
				// nop
			}

			@Override
			public void windowClosed(WindowEvent e) {
				owner.refresh();
			}

			@Override
			public void windowActivated(WindowEvent e) {
				// nop
			}
		});

		initTabbedPanel();

		this.add(tpnTabs, BorderLayout.CENTER);
		pack();
		WindowManipulator.centerWindow(this);
	}

	/**
	 * 
	 */
	private void initTabbedPanel() {
		tpnTabs = new JTabbedPane();

		initPanelComponents();
		tpnTabs.addTab("Komponenty", pnlComponents);

		initPanelDangers();
		tpnTabs.addTab("Definice nebezpečí", pnlDangers);

		initComponentPopupMenu();

		initDangersPopupMenu();

	}

	/**
	 * 
	 */
	private void initComponentPopupMenu() {
		pmnComponentsPopup = new JPopupMenu("Možnosti komponenty");

		mniAddComponent = new JMenuItem("vložit");
		mniAddComponent.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				AdminFrame.this.mniAddComponentPerformed();
			}
		});
		pmnComponentsPopup.add(mniAddComponent);

		mniUpdateComponent = new JMenuItem("upravit");
		mniUpdateComponent.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				AdminFrame.this.mniUpdateComponentPerformed();
			}
		});
		pmnComponentsPopup.add(mniUpdateComponent);

		mniDeleteComponent = new JMenuItem("smazat");
		mniDeleteComponent.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				AdminFrame.this.mniDeleteComponentPerformed();
			}
		});
		pmnComponentsPopup.add(mniDeleteComponent);

		tblComponents.add(pmnComponentsPopup);
	}

	/**
	 * 
	 */
	protected void mniAddComponentPerformed() {
		Component newComponent = new Component(0, "", "");
		new ComponentDangerVariantFrame(this, newComponent, dangerGroups);
	}

	/**
	 * 
	 */
	protected void mniUpdateComponentPerformed() {
		int selectedComponentIndex = tblComponents.getSelectedRow();
		if (selectedComponentIndex >= 0) {
			ComponentTableModel componentTableModel = ((ComponentTableModel) tblComponents
					.getModel());
			Component currentComponent = componentTableModel.getData().get(
					selectedComponentIndex);

			new ComponentDangerVariantFrame(this, currentComponent,
					dangerGroups);
		}
	}

	/**
	 * 
	 */
	protected void mniDeleteComponentPerformed() {
		int selectedComponentIndex = tblComponents.getSelectedRow();
		if (selectedComponentIndex >= 0) {
			ComponentTableModel componentTableModel = ((ComponentTableModel) tblComponents
					.getModel());
			Component currentComponent = componentTableModel.getData().get(
					selectedComponentIndex);
			if (JOptionPane.showConfirmDialog(this,
					"Oravdu si přejete odstranit komponentu \""
							+ currentComponent.getName()
							+ "\" jejích přiřazení k nebezpečím?") == JOptionPane.YES_OPTION) {
				currentComponent.deleteFromDB(getConnection());
				componentTableModel.getData().remove(selectedComponentIndex);
				componentTableModel.fireTableDataChanged();
				owner.refresh();
			}
		}
	}

	/**
	 * 
	 */
	private void initDangersPopupMenu() {
		pmnDangersPopup = new JPopupMenu("Možnosti");

		mniAddDanger = new JMenuItem("vložit");
		mniAddDanger.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				AdminFrame.this.mniAddPerformed();
			}
		});
		pmnDangersPopup.add(mniAddDanger);

		mniUpdateDanger = new JMenuItem("upravit");
		mniUpdateDanger.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				AdminFrame.this.mniUpdatePerformed();
			}
		});
		pmnDangersPopup.add(mniUpdateDanger);

		mniDeleteDanger = new JMenuItem("smazat");
		mniDeleteDanger.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				AdminFrame.this.mniDeletePerformed();
			}
		});
		pmnDangersPopup.add(mniDeleteDanger);

		treDangers.add(pmnDangersPopup);
	}

	/**
	 * 
	 */
	@SuppressWarnings("unchecked")
	protected void mniAddPerformed() {
		DefaultMutableTreeNode selectedNode = ((DefaultMutableTreeNode) treDangers
				.getLastSelectedPathComponent());
		if (selectedNode != null) {
			Object nodeObject = selectedNode.getUserObject();
			if (nodeObject instanceof DangerGroupList) {
				// vložení nové skupiny
				String name = JOptionPane
						.showInputDialog("Název skupiny nebezpečí");
				if (name != null) {
					DangerGroup dg = new DangerGroup(0, name);
					dg.saveToDB(getConnection());
					refreshTree();
				}
			} else if (nodeObject instanceof DangerGroup) {
				// vloženi noveho typu do skupiny

				DangerGroup dg = (DangerGroup) nodeObject;
				DangerType newType = new DangerType(dg, 0, "", "", "", "", "",
						"", "", "", "", "");
				ArrayList<DangerGroup> groups = (ArrayList<DangerGroup>) ((DefaultMutableTreeNode) treDangers
						.getModel().getRoot()).getUserObject();
				new AdminDangerTypeFrame(this, newType, groups);
			} else if (nodeObject instanceof DangerType) {
				// vložení nové varianty do typu
				DangerType dt = (DangerType) nodeObject;
				DangerVariant dv = new DangerVariant(dt, 0, "");
				new AdminDangerVariantFrame(this, dv);
			}
			// else if (nodeObject instanceof DangerVariant) {
			// DangerVariant dv = (DangerVariant) nodeObject;
			// new AdminDangerVariantFrame(this, new DangerVariant(dv
			// .getDangerType(), 0, ""));
			// }
		}
	}

	/**
	 * 
	 */
	@SuppressWarnings("unchecked")
	protected void mniUpdatePerformed() {
		DefaultMutableTreeNode selectedNode = ((DefaultMutableTreeNode) treDangers
				.getLastSelectedPathComponent());
		if (selectedNode != null) {
			Object nodeObject = selectedNode.getUserObject();
			if (nodeObject instanceof DangerGroup) {
				DangerGroup dg = (DangerGroup) nodeObject;
				String newName = JOptionPane.showInputDialog("Název", dg
						.getName());
				if (newName != null) {
					dg.setName(newName);
					dg.saveToDB(owner.getApplication().getConnection());
					refreshTree();
				}
			} else if (nodeObject instanceof DangerType) {

				DangerType dt = (DangerType) nodeObject;
				ArrayList<DangerGroup> groups = (ArrayList<DangerGroup>) ((DefaultMutableTreeNode) treDangers
						.getModel().getRoot()).getUserObject();
				new AdminDangerTypeFrame(this, dt, groups);
			} else if (nodeObject instanceof DangerVariant) {
				DangerVariant dv = (DangerVariant) nodeObject;
				new AdminDangerVariantFrame(this, dv);
			}
		}
	}

	/**
	 * 
	 */
	protected void mniDeletePerformed() {
		DefaultMutableTreeNode selectedNode = ((DefaultMutableTreeNode) treDangers
				.getLastSelectedPathComponent());
		if (selectedNode != null) {
			Object nodeObject = selectedNode.getUserObject();
			if (nodeObject instanceof DangerVariant) {
				DangerVariant dv = (DangerVariant) nodeObject;
				if (JOptionPane.showConfirmDialog(this,
						"Opravdu si přejete smazat variantu \""
								+ dv.getDescription() + "\"?") == JOptionPane.YES_OPTION) {
					dv.deleteFromDB(getConnection());
					refreshTree();
				}
			} else if (nodeObject instanceof DangerType) {
				DangerType dt = (DangerType) nodeObject;
				if (JOptionPane.showConfirmDialog(this,
						"Opravdu si přejete smazat typ \""
								+ dt.getDescription() + "\"?") == JOptionPane.YES_OPTION
						&& JOptionPane.showConfirmDialog(this,
								"Při smazání typu nebezpečí"
										+ " dojde ke smazání všech jeho"
										+ " variant včetně přiřazení"
										+ " ke komponentám. Souhlasíte?") == JOptionPane.YES_OPTION) {
					dt.deleteFromDB(getConnection());
					refreshTree();
				}
			} else if (nodeObject instanceof DangerGroup) {
				DangerGroup dg = (DangerGroup) nodeObject;
				if (JOptionPane.showConfirmDialog(this,
						"Opravdu si přejete smazat skupinu \"" + dg.getName()
								+ "\"?") == JOptionPane.YES_OPTION
						&& JOptionPane.showConfirmDialog(this,
								"Při smazání skupiny nebezpečí"
										+ " dojde ke smazání všech jích"
										+ " typů včetně přiřazení"
										+ " ke komponentám a jejich"
										+ " variant. Souhlasíte?") == JOptionPane.YES_OPTION) {
					dg.deleteFromDB(getConnection());
					refreshTree();
				}
			}
		}
	}

	/**
	 * 
	 */
	private void initPanelComponents() {
		pnlComponents = new JPanel();
		ComponentCatalog cs = owner.getApplication().getComponentCatalog();
		tblComponents = new JTable(new ComponentTableModel(this, cs
				.getComponents()));
		tblComponents.addMouseListener(new ComponentsPopupListener());

		JScrollPane scroll = new JScrollPane(tblComponents);
		scroll.setViewportView(tblComponents);
		scroll.setPreferredSize(new Dimension(500, 300));

		pnlComponents.add(scroll, BorderLayout.CENTER);
	}

	/**
	 * 
	 */
	private void initPanelDangers() {
		pnlDangers = new JPanel();

		treDangers = new JTree();
		treDangers.addMouseListener(new DangersPopupListener());
		refreshTree();

		JScrollPane scroll = new JScrollPane(treDangers);
		scroll.setViewportView(treDangers);
		scroll.setPreferredSize(new Dimension(500, 300));

		pnlDangers.add(scroll);
	}

	/**
	 * 
	 */
	protected void refreshTree() {
		dangerGroups.clear();
		DefaultMutableTreeNode root = new DefaultMutableTreeNode(dangerGroups);

		try {
			Statement stmt_dg = owner.getApplication().getConnection()
					.createStatement();
			Statement stmt_dt = owner.getApplication().getConnection()
					.createStatement();
			Statement stmt_dv = owner.getApplication().getConnection()
					.createStatement();

			stmt_dg.executeQuery("SELECT id, name FROM danger_group");
			ResultSet rs_dg = stmt_dg.getResultSet();
			DefaultMutableTreeNode dg_node;
			while (rs_dg.next()) {
				DangerGroup dg = new DangerGroup(rs_dg.getInt("id"), rs_dg
						.getString("name"));
				dg_node = new DefaultMutableTreeNode(dg);
				stmt_dt
						.executeQuery("SELECT * FROM danger_type WHERE danger_group_id='"
								+ rs_dg.getInt("id") + "';");

				ResultSet rs_dt = stmt_dt.getResultSet();
				DefaultMutableTreeNode dt_node;
				while (rs_dt.next()) {
					DangerType dt = new DangerType(dg, rs_dt.getInt(1), rs_dt
							.getString(3), rs_dt.getString(4), rs_dt
							.getString(5), rs_dt.getString(6), rs_dt
							.getString(7), rs_dt.getString(8), rs_dt
							.getString(9), rs_dt.getString(10), rs_dt
							.getString(11), rs_dt.getString(12));
					dt_node = new DefaultMutableTreeNode(dt);
					stmt_dv
							.executeQuery("SELECT id, description FROM danger_variant WHERE danger_type_id='"
									+ rs_dt.getInt("id") + "';");

					ResultSet rs_dv = stmt_dv.getResultSet();
					DefaultMutableTreeNode dv_node;
					while (rs_dv.next()) {
						DangerVariant dv = new DangerVariant(dt, rs_dv
								.getInt("id"), rs_dv.getString("description"));
						dv_node = new DefaultMutableTreeNode(dv);
						dt_node.add(dv_node);
						dt.addDangerVariant(dv);
					}
					dg_node.add(dt_node);
					dg.addDangerType(dt);
				}
				root.add(dg_node);
				dangerGroups.add(dg);
			}

			stmt_dv.close();
			stmt_dt.close();
			stmt_dg.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		((DefaultTreeModel) treDangers.getModel()).setRoot(root);
	}

	public Connection getConnection() {
		return owner.getApplication().getConnection();
	}

	private class DangersPopupListener extends MouseAdapter {
		@Override
		public void mousePressed(MouseEvent e) {
			maybeShowPopup(e);
		}

		@Override
		public void mouseReleased(MouseEvent e) {
			maybeShowPopup(e);
		}

		private void maybeShowPopup(MouseEvent e) {
			if (e.isPopupTrigger()) {
				DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) treDangers
						.getLastSelectedPathComponent();
				if (selectedNode == null) {
					return;
				}
				Object nodeObject = selectedNode.getUserObject();
				if (nodeObject instanceof DangerGroupList) {
					mniAddDanger.setVisible(true);
					mniAddDanger.setText("vložit skupinu");
					mniUpdateDanger.setVisible(false);
					mniDeleteDanger.setVisible(false);
				} else if (nodeObject instanceof DangerGroup) {
					mniAddDanger.setVisible(true);
					mniAddDanger.setText("vložit typ");
					mniUpdateDanger.setVisible(true);
					mniUpdateDanger.setText("upravit skupinu");
					mniDeleteDanger.setVisible(true);
					mniDeleteDanger.setText("smazat skupinu");
				} else if (nodeObject instanceof DangerType) {
					mniAddDanger.setVisible(true);
					mniAddDanger.setText("vložit variantu");
					mniUpdateDanger.setVisible(true);
					mniUpdateDanger.setText("upravit typ");
					mniDeleteDanger.setVisible(true);
					mniDeleteDanger.setText("smazat typ");
				} else if (nodeObject instanceof DangerVariant) {
					mniAddDanger.setVisible(false);
					mniUpdateDanger.setVisible(true);
					mniUpdateDanger.setText("upravit variantu");
					mniDeleteDanger.setVisible(true);
					mniDeleteDanger.setText("smazat variantu");
				} else {
					return;
				}
				pmnDangersPopup.show(e.getComponent(), e.getX(), e.getY());
			}
		}
	}

	private class ComponentsPopupListener extends MouseAdapter {
		@Override
		public void mousePressed(MouseEvent e) {
			maybeShowPopup(e);
		}

		@Override
		public void mouseReleased(MouseEvent e) {
			maybeShowPopup(e);
		}

		private void maybeShowPopup(MouseEvent e) {
			if (e.isPopupTrigger()) {
				pmnComponentsPopup.show(e.getComponent(), e.getX(), e.getY());
			}
		}
	}

	protected class DangerGroupList extends ArrayList<DangerGroup> {
		/**
		 * 
		 */
		private static final long serialVersionUID = 6446228818721535648L;

		public DangerGroupList() {
			super(10);
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see java.util.AbstractCollection#toString()
		 */
		@Override
		public String toString() {
			return "Rizika";
		}
	}

	@Override
	public MainFrame getOwner() {
		return owner;
	};
}
