/*
 * Copyright (c) 2007, Going Dot Com Inc. All rights reserved.
 */

package jp.co.going.xbrl.sample;

import java.awt.BorderLayout;
import java.awt.Container;
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.sql.Connection;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;

import jp.co.going.xbrl.common.XbException;
import jp.co.going.xbrl.sample.dao.XbEntityDao;
import jp.co.going.xbrl.sample.dao.XbEntityIdentifierDao;
import jp.co.going.xbrl.sample.dao.XbEntitySegmentDao;
import jp.co.going.xbrl.sample.dao.XbEtcDao;
import jp.co.going.xbrl.sample.dao.XbIdentifierDao;
import jp.co.going.xbrl.sample.dao.obj.XbEntityIdentifierObj;
import jp.co.going.xbrl.sample.dao.obj.XbEntityObj;
import jp.co.going.xbrl.sample.dao.obj.XbEtcObj;
import jp.co.going.xbrl.sample.dao.obj.XbIdentifierObj;
import jp.co.going.xbrl.sample.dao.obj.XbMainEtcObj;

/**
 * @author Masako Okayasu
 */
@SuppressWarnings("serial")
public class XbEntityInput extends XbTreeDataSet implements ActionListener {

	private Connection conn = null;
	private XbEntityDao entityDao = null;
	private XbEntityIdentifierDao entityIdentifierDao = null;
	private XbEntitySegmentDao entitySegmentDao = null;
	private XbIdentifierDao identifierDao = null;
	private XbEtcDao etcDao = null;

	private XbMyTreeNode rootNode = new XbMyTreeNode("（登録済リスト）");
	private JButton expButton = new JButton("展開");
	private String[] dataList = null;

	private String current = null;
	private int sampleCount = 1;
	private boolean childFlag = false;
	private boolean identifierFlag = false;
	private int menuFlag = 0;

	private int insertFlag = 0;
	private long entityID = 0;
	private String prefix = "";
	private String uri = "";

	public XbEntityInput(Connection conn) {
		this.conn = conn;

		setTitle("XBRL Toolkit : Input " + ENTITY);
		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		} catch (Exception e) {
			e.printStackTrace();
		}

		entityDao = XbEntityDao.getInstance(conn);
		entityIdentifierDao = XbEntityIdentifierDao.getInstance(conn);
		entitySegmentDao = XbEntitySegmentDao.getInstance(conn);
		identifierDao = XbIdentifierDao.getInstance(conn);
		etcDao = XbEtcDao.getInstance(conn);


		Container container = getContentPane();
		container.setLayout(new BorderLayout());

		JPanel HeaderPanel = HeaderPanel();
		JPanel MainPanel = MainPanel();
		JPanel SubmitPanel = SubmitPanel();

		submitButton.addActionListener(this);
		submitButton.setEnabled(false);
		closeButton.addActionListener(this);

		container.add(HeaderPanel, BorderLayout.NORTH);
		container.add(MainPanel, BorderLayout.CENTER);
		container.add(SubmitPanel, BorderLayout.SOUTH);

		pack();
	}

	/**
	 * 画面Header欄の生成
	 */
	private JPanel HeaderPanel() {
		JPanel HeaderPanel = new JPanel();
		HeaderPanel.setLayout(new BorderLayout());

		HeaderPanel.add(new JLabel("　【 " + nameList.get(ENTITY) + "定義 】　　"), BorderLayout.WEST);

		expButton.addActionListener(this);
		HeaderPanel.add(setPanel(expButton), BorderLayout.CENTER);

		return HeaderPanel;
	}

	/**
	 * Entity入力欄の生成
	 */
	private JPanel MainPanel() {
		JPanel MainPanel = new JPanel();
		MainPanel.setLayout(new BorderLayout());

		try {
			ArrayList<XbEntityObj> tableData = entityDao.selectAll();
			for(int i=0; i<tableData.size(); i++) {
				XbEntityObj entityObj = tableData.get(i);

				// エンティティ
				XbMyTreeNode entityNode = new XbMyTreeNode("<" + ENTITY + ">： " + entityObj.getEntity_name());
				entityNode.setID(entityObj.getEntity_id());
				rootNode.add(entityNode);

				// identifier
				XbMyTreeNode identifierNode = new XbMyTreeNode("<" + IDENTIFIER + ">");
				entityNode.add(identifierNode);

				ArrayList<XbEntityIdentifierObj> list1 = entityIdentifierDao.selectAll(entityObj.getEntity_id());
				for(int j=0; j<list1.size(); j++) {
					XbEntityIdentifierObj entityIdentifierObj = list1.get(j);

					XbMyTreeNode identifierName = new XbMyTreeNode(entityIdentifierObj.getIdentifier_name());
					identifierName.setType(IDENTIFIER);
					identifierName.setID(entityIdentifierObj.getIdentifier_id());
					identifierNode.add(identifierName);
				}

				// セグメント
				HashMap<Long, TreePath> parent_id = new HashMap<Long, TreePath>();
				parent_id.put((long)0, new TreePath(entityNode.getPath()));
				ArrayList<XbMainEtcObj> list2 = null;
				prefixFlag = true;

				// セグメントの枝ノードの生成
				Iterator ite = parent_id.entrySet().iterator();
				while(ite.hasNext()) {
					parent_id = new HashMap<Long, TreePath>();

					while(ite.hasNext()) {
						Entry ent = (Entry)ite.next();
						long key = (Long)ent.getKey();
						TreePath val = (TreePath)ent.getValue();
						XbMyTreeNode parentNode = (XbMyTreeNode)val.getLastPathComponent();

						list2 = entitySegmentDao.selectAll(entityObj.getEntity_id(), key);
						parent_id = makeTreeNode(parent_id, key, parentNode, SEGMENT, list2);
					}

					ite = parent_id.entrySet().iterator();
				}
			}

			treeModel = new DefaultTreeModel(rootNode);
			tree = new JTree(treeModel);
			tree.setToggleClickCount(1);
			tree.setSelectionRow(0);
			selectNode = rootNode;

			JScrollPane scroll = new JScrollPane();
			scroll.getViewport().setView(tree);
			scroll.setPreferredSize(new Dimension(400, 300));
			MainPanel.add(scroll, BorderLayout.NORTH);

			JLabel tooltip = new JLabel(TOOLTIP1);
			tooltip.setFont(setFont(11));
			tooltip.setPreferredSize(new Dimension(400, 26));
			MainPanel.add(tooltip, BorderLayout.SOUTH);

			popMenu();
			setMouseAdapter();

		} catch (Exception ex) {
			ex.printStackTrace();
		}

		return MainPanel;
	}

	/**
	 * 右クリックメニューの生成
	 */
	private void popMenu() {
		popMenu = new JPopupMenu();

		if(menuFlag==0) {
			popMenuItem[0] = new JMenuItem(ENTITY + "追加");
			popMenuItem[0].addActionListener(this);
			popMenu.add(popMenuItem[0]);
		}

		if(menuFlag==1 && identifierFlag==false) {
			popMenuItem[1] = new JMenuItem(IDENTIFIER + "追加");
			popMenuItem[1].addActionListener(this);
			popMenu.add(popMenuItem[1]);
		}

		if(menuFlag==1) {
			popMenuItem[2] = new JMenuItem(SEGMENT + "追加");
			popMenuItem[2].addActionListener(this);
			popMenu.add(popMenuItem[2]);
		}

		if(menuFlag==3 || menuFlag==4 || menuFlag==5 || menuFlag==6) {
			popMenuItem[4] = new JMenuItem("接頭辞の指定");
			popMenuItem[4].addActionListener(this);
			popMenu.add(popMenuItem[4]);
		}

		if(menuFlag==2 || menuFlag==5 || menuFlag==6 || menuFlag==7 || menuFlag==8) {
			popMenuItem[5] = new JMenuItem("アイテム指定");
			popMenuItem[5].addActionListener(this);
			popMenu.add(popMenuItem[5]);
		}

		if(menuFlag==7 || menuFlag==8) {
			popMenuItem[6] = new JMenuItem("子アイテム追加");
			popMenuItem[6].addActionListener(this);
			popMenu.add(popMenuItem[6]);
		}

		if(menuFlag==1 || menuFlag==9) {
			popMenuItem[7] = new JMenuItem("名前変更");
			popMenuItem[7].addActionListener(this);
			popMenu.add(popMenuItem[7]);
		}

		if(menuFlag != 0) {
			popMenuItem[8] = new JMenuItem("削除");
			popMenuItem[8].addActionListener(this);
			popMenu.add(popMenuItem[8]);
		}
	}

	/**
	 * MouseAdapterの登録
	 */
	private void setMouseAdapter() {
		tree.addMouseListener(new MouseAdapter() {
			public void mousePressed(MouseEvent e) {
				int selectRow = tree.getRowForLocation(e.getX(), e.getY());
				if(selectRow != -1) {
					tree.setSelectionRow(selectRow);
					selectNode = (XbMyTreeNode)tree.getLastSelectedPathComponent();
					selectNodeName = selectNode.getUserObject().toString();

					if(SwingUtilities.isRightMouseButton(e)) {
						if(selectNode == rootNode) {
							menuFlag = 0;
						} else if(selectNodeName.indexOf(" sample") != -1) {
							menuFlag = 9;
						} else if(selectNodeName.indexOf("<" + ENTITY + ">： ") != -1) {
							current = ENTITY;
							menuFlag = 1;
							for(int i=0; i<selectNode.getChildCount(); i++) {
								String childNodeName = ((XbMyTreeNode)selectNode.getChildAt(i)).getUserObject().toString();
								if(childNodeName.indexOf("<" + IDENTIFIER + ">") != -1) {
									identifierFlag = true;
							}	}
						} else if(selectNodeName.indexOf("<" + IDENTIFIER + ">") != -1) {
							current = IDENTIFIER;
							menuFlag = 2;
						} else if(selectNodeName.indexOf("<" + SEGMENT + ">") != -1) {
							current = SEGMENT;
							if(selectNodeName.indexOf("　URI=") != -1) {
								menuFlag = 5;
							} else {
								menuFlag = 3;
							}
						} else if(selectNodeName.indexOf("<" + SCENARIO + ">") != -1) {
							current = SCENARIO;
							if(selectNodeName.indexOf("　URI=") != -1) {
								menuFlag = 6;
							} else {
								menuFlag = 4;
							}
						} else {
							childFlag = true;
							if(selectNode.getType().equals(IDENTIFIER)) {
								current = IDENTIFIER;
								menuFlag = 2;
							} else if(selectNode.getType().equals(SEGMENT)) {
								current = SEGMENT;
								menuFlag = 7;
							} else if(selectNode.getType().equals(SCENARIO)) {
								current = SCENARIO;
								menuFlag = 8;
							}
						}
						popMenu();
						popMenu.show(e.getComponent(), e.getX(), e.getY());
		}	}	}	});
	}

	/**
	 * Button, MenuItem のイベントを取得
	 */
	public void actionPerformed(ActionEvent e) {
		Object source = e.getSource();

		// 登録済リスト
		try {
			if(menuFlag==2) {
				ArrayList<XbIdentifierObj> list = identifierDao.selectAll();
				dataList = new String[list.size()];
				for(int i=0; i<list.size(); i++) {
					XbIdentifierObj obj = list.get(i);
					dataList[i] = String.valueOf(obj.getIdentifier_id()) + ". " + obj.getIdentifier_name();
			}	}
			else if(menuFlag >= 5 && menuFlag <= 8) {
				ArrayList<XbEtcObj> list = etcDao.selectAll(etcType.get(current));
				dataList = new String[list.size()];
				for(int i=0; i<list.size(); i++) {
					XbEtcObj obj = list.get(i);
					dataList[i] = String.valueOf(obj.getEtc_id()) + ". " + obj.getEtc_name();
			}	}
		} catch (Exception ex) {
			ex.printStackTrace();
		}

		if(source == popMenuItem[0]) {
			addNode("<" + ENTITY + ">： ( sample" + sampleCount + " )");
			sampleCount++;
		}
		else if(source == popMenuItem[1]) {
			addNode("<" + IDENTIFIER + ">");
		}
		else if(source == popMenuItem[2]) {
			addNode("<" + SEGMENT + ">");
		}
		else if(source == popMenuItem[3]) {
			addNode("<" + SCENARIO + ">");
		}
		else if(source == popMenuItem[4]) {
			if(setNodePrefix()) {
				submitButton.setEnabled(true);
		}	}
		else if(source == popMenuItem[5]) {
			if(setNodeValue(childFlag, dataList, dataList.length>0 ? dataList[0] : null, current)) {
				submitButton.setEnabled(true);
		}	}
		else if(source == popMenuItem[6]) {
			if(setNodeValue(false, dataList, dataList.length>0 ? dataList[0] : null, current)) {
				submitButton.setEnabled(true);
		}	}
		else if(source == popMenuItem[7]) {
			setNewNodeName();
		}
		else if(source == popMenuItem[8]) {
			if(delNode()) {
				submitButton.setEnabled(true);
		}	}
		else if(source == submitButton) {
			try {
				getNodeValue(rootNode);
				conn.commit();

				JOptionPane.showMessageDialog(this, "データを登録しました。");
				submitButton.setEnabled(false);

			} catch (Exception ex) { 
				ex.printStackTrace();
		}	}
		else if(source == closeButton){
			this.setVisible(false);
		}

		childFlag = false;
		identifierFlag = false;

		treeModel.reload();
		tree.expandPath(new TreePath(selectNode));
		tree.setSelectionPath(new TreePath(selectNode.getPath()));
		selectNode = (XbMyTreeNode)tree.getLastSelectedPathComponent();

		if(source == expButton) {
			for(int i=0; i<tree.getRowCount(); i++) {
				tree.expandRow(i);
			}
		}
	}

	/**
	 * ノードの値を取得
	 */
	private void getNodeValue(XbMyTreeNode Node) {
		try {
			for(int i=0; i<Node.getChildCount(); i++) {
				XbMyTreeNode childNode = (XbMyTreeNode)Node.getChildAt(i);
				String childNodeName = childNode.getUserObject().toString();

				// エンティティ登録
				if(childNodeName.indexOf("<" + ENTITY + ">： ") != -1) {
					if(childNode.getID() != 0) {
						entityID = 0;
					} else {
						entityID = entityDao.getNextId();

						XbEntityObj entityObj = new XbEntityObj();
						entityObj.setEntity_id(entityID);
						entityObj.setEntity_name(childNodeName.substring(childNodeName.indexOf("： ")+2));
						entityObj.setCreation_date(new Date());
						entityDao.insert(entityObj);
						insertFlag = 1;
				}	}

				if(entityID != 0) {
					// identifier登録
					if(insertFlag==2) {
						XbEntityIdentifierObj entityIdentifierObj = new XbEntityIdentifierObj();
						entityIdentifierObj.setEntity_id(entityID);
						entityIdentifierObj.setIdentifier_id(childNode.getID());
						entityIdentifierObj.setCreation_date(new Date());
						entityIdentifierDao.insert(entityIdentifierObj);
					}
					if(childNodeName.indexOf("<" + IDENTIFIER + ">") != -1) {
						insertFlag = 2;
					}

					// Segment登録
					if(insertFlag==3) {

						// レコードの存在確認
						XbMainEtcObj mainEtcObj = entitySegmentDao.select(entityID, Node.getID(), childNode.getID(), prefix); 

						if(mainEtcObj==null) {
							mainEtcObj = new XbMainEtcObj();
							mainEtcObj.setMain_id(entityID);
							mainEtcObj.setEtc_type(etcType.get(SEGMENT));
							mainEtcObj.setEtc_id(childNode.getID());
							mainEtcObj.setParent_etc_id(Node.getID());
							mainEtcObj.setPrefix(prefix);
							mainEtcObj.setUri(uri);
							mainEtcObj.setCreation_date(new Date());
							entitySegmentDao.insert(mainEtcObj);
						}
					}
					if(childNodeName.indexOf("<" + SEGMENT + ">： ") != -1) {
						String temp = childNodeName.substring(childNodeName.indexOf("Prefix=")+7).replace("\"", "");
						prefix = temp.substring(0, temp.indexOf("　"));
						uri = temp.substring(temp.indexOf("　URI=")+5);
						insertFlag = 3;
					}

					// さらに深部へ
					if(childNode.getChildCount() > 0) {
						getNodeValue(childNode);
					}
			}	}
		} catch (XbException err) {
			try {
				err.printStackTrace();
				conn.rollback();
			}
			catch (Exception ex) {
				ex.printStackTrace();
			}
		} catch (Exception ex) { 
			ex.printStackTrace();
		}
	}
}