/*
 * 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.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.XbRefAttributesDao;
import jp.co.going.xbrl.sample.dao.XbRefDao;
import jp.co.going.xbrl.sample.dao.obj.XbRefAttributesObj;
import jp.co.going.xbrl.sample.dao.obj.XbRefObj;

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

	private Connection conn = null;
	private XbRefDao refDao = null;
	private XbRefAttributesDao refAttrDao = null;

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

	private int sampleCount = 1;
	private boolean childFlag = false;

	private int insertFlag = 0;
	private long refID = 0;

	/**
	 * コンストラクタ
	 */
	public XbRefInput(Connection conn) {
		this.conn = conn;

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

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

		refDao = XbRefDao.getInstance(conn);
		refAttrDao = XbRefAttributesDao.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);

		popMenu();
		setMouseAdapter();

		pack();
	}

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

		HeaderPanel.add(new JLabel("　【 " + nameList.get(REF) + "登録 <" + REF + "> 】　　"), BorderLayout.WEST);

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

		return HeaderPanel;
	}

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

		try {
			// セグメントの枝ノードの生成
			Iterator ite = refType.entrySet().iterator();
			while(ite.hasNext()) {
				Entry ent = (Entry)ite.next();
				String key = (String)ent.getKey();
				int val = (Integer)ent.getValue();

				ArrayList<XbRefObj> tableData = refDao.selectAllByType(val);
				if(tableData.size() > 0) {
					XbMyTreeNode titleNode = new XbMyTreeNode("<" + key + ">");
					rootNode.add(titleNode);

					for(int i=0; i<tableData.size(); i++) {
						XbRefObj refObj = tableData.get(i);

						// Ref
						XbMyTreeNode refNode = new XbMyTreeNode(refObj.getRef_name());
						refNode.setType(key);
						refNode.setID(refObj.getRef_id());
						titleNode.add(refNode);

						ArrayList<XbRefAttributesObj> list = refAttrDao.selectAll(refObj.getRef_type(), refObj.getRef_id());
						for(int j=0; j<list.size(); j++) {
							XbRefAttributesObj refAttributesObj = list.get(j);

							// Ref Attributes
							String nodeTitle = "属性： " + refAttributesObj.getName() + "=\"" + refAttributesObj.getValue() + "\"";
							XbMyTreeNode attrNode = new XbMyTreeNode(nodeTitle);
							attrNode.setType(key);
							attrNode.setID(refAttributesObj.getRef_id());
							refNode.add(attrNode);
			}	}	}	}

			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(SCHEMAREF + "追加");
			popMenuItem[0].addActionListener(this);
			popMenu.add(popMenuItem[0]);

			popMenuItem[1] = new JMenuItem(LINKBASEREF + "追加");
			popMenuItem[1].addActionListener(this);
			popMenu.add(popMenuItem[1]);

			popMenuItem[2] = new JMenuItem(ROLEREF + "追加");
			popMenuItem[2].addActionListener(this);
			popMenu.add(popMenuItem[2]);

			popMenuItem[3] = new JMenuItem(ARCROLEREF + "追加");
			popMenuItem[3].addActionListener(this);
			popMenu.add(popMenuItem[3]);
		}

		if(menuFlag==1) {
			popMenuItem[4] = new JMenuItem("要素の追加");
			popMenuItem[4].addActionListener(this);
			popMenu.add(popMenuItem[4]);
		}

		if(menuFlag==2 || menuFlag==5) {
			popMenuItem[5] = new JMenuItem("属性の指定");
			popMenuItem[5].addActionListener(this);
			popMenu.add(popMenuItem[5]);
		}

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

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

	/**
	 * MouseAdapterの登録
	 */
	private void setMouseAdapter() {
		tree.addMouseListener(new MouseAdapter() {
			public void mousePressed(MouseEvent e) {
				if(SwingUtilities.isRightMouseButton(e)) {
					int selectRow = tree.getRowForLocation(e.getX(), e.getY());

					if(selectRow != -1) {
						tree.setSelectionRow(selectRow);
						selectNode = (XbMyTreeNode)tree.getLastSelectedPathComponent();
						selectNodeName = selectNode.getUserObject().toString();

						if(selectNode == rootNode) {
							menuFlag = 0;
						} else if(selectNodeName.indexOf(" sample") != -1) {
							menuFlag = 9;
						} else if(selectNodeName.indexOf("<" + SCHEMAREF + ">") != -1) {
							menuFlag = 1;
						} else if(selectNodeName.indexOf("<" + LINKBASEREF + ">") != -1) {
							menuFlag = 1;
						} else if(selectNodeName.indexOf("<" + ROLEREF + ">") != -1) {
							menuFlag = 1;
						} else if(selectNodeName.indexOf("<" + ARCROLEREF + ">") != -1) {
							menuFlag = 1;
						} else 	if(selectNodeName.indexOf("属性： ") != -1) {
							menuFlag = 2;
							childFlag = true;
						} else {
							menuFlag = 5;
						}
						popMenu();
						popMenu.show(e.getComponent(), e.getX(), e.getY());
		}	}	}	});
	}

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

		if(source == popMenuItem[0]) {
			addNode("<" + SCHEMAREF + ">");
		}
		else if(source == popMenuItem[1]) {
			addNode("<" + LINKBASEREF + ">");
		}
		else if(source == popMenuItem[2]) {
			addNode("<" + ROLEREF + ">");
		}
		else if(source == popMenuItem[3]) {
			addNode("<" + ARCROLEREF + ">");
		}
		else if(source == popMenuItem[4]) {
			XbMyTreeNode childNode = new XbMyTreeNode("( sample" + sampleCount + " )");
			childNode.setType(selectNodeName.replace("<", "").replace(">", ""));
			selectNode.add(childNode);
			sampleCount++;
		}
		else if(source == popMenuItem[5]) {
			if(setNodeAttributes()) {
				submitButton.setEnabled(true);
		}	}
		else if(source == popMenuItem[6]) {
			setNewNodeName2();
		}
		else if(source == popMenuItem[7]) {
			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;

		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 setNewNodeName2() {
		Object newName = JOptionPane.showInputDialog(this, "新しい名前：", "入力", JOptionPane.INFORMATION_MESSAGE, null, null, selectNodeName);
		if(newName != null && !newName.equals("")) {
			selectNode.setUserObject(newName.toString().trim());
	}	}

	/**
	 * 属性の入力欄の生成
	 */
	private boolean setNodeAttributes() {
		String name = "", value = "";
		boolean rc = false;

		if(selectNodeName.indexOf("： ") != -1) {
			String temp = selectNodeName.substring(selectNodeName.indexOf("： ")+2).replace("\"", "");
			name = temp.substring(0, temp.indexOf("="));
			value = temp.substring(temp.indexOf("=")+1);
		}

		Object attrName = JOptionPane.showInputDialog(this, "属性の名称を入力して下さい：", "入力", JOptionPane.INFORMATION_MESSAGE, null, null, name);
		if(attrName != null && !attrName.equals("")) {

			Object attrValue = JOptionPane.showInputDialog(this, "属性の値を入力して下さい：", "入力", JOptionPane.INFORMATION_MESSAGE, null, null, value);
			if(attrValue != null && !attrValue.equals("")) {
				String val = "属性： " + attrName.toString().trim() + "=\"" + attrValue.toString().trim() + "\"";

				if(childFlag==true) {
					selectNode.setUserObject(val);
				}
				else {
					XbMyTreeNode fieldNode = new XbMyTreeNode(val);
					fieldNode.setType(selectNode.getType());
					selectNode.add(fieldNode);
				}
				rc = true;
		}	}
		return rc;
	}

	/**
	 * ノードの値を取得
	 */
	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(childNode.getID()==0 && childNode.getType() != null) {

					// フラグ切り替え
					if(insertFlag==2 && childNodeName.indexOf("属性： ") == -1) {
						insertFlag = 1;
					}

					// Ref Attributes
					if(insertFlag==2) {
						String temp = childNodeName.substring(childNodeName.indexOf("： ")+2).replace("\"", "");
						String name = temp.substring(0, temp.indexOf("="));
						String value = temp.substring(temp.indexOf("=")+1);

						// レコードの存在確認
						XbRefAttributesObj refAttrObj = refAttrDao.select(refType.get(childNode.getType()), refID, name); 

						if(refAttrObj == null) {
							refAttrObj = new XbRefAttributesObj();
							refAttrObj.setRef_type(refType.get(childNode.getType()));
							refAttrObj.setRef_id(refID);
							refAttrObj.setName(name);
							refAttrObj.setValue(value);
							refAttrObj.setCreation_date(new Date());
							refAttrDao.insert(refAttrObj);
					}	}

					// Ref
					if(insertFlag==1) {
						refID = refDao.getNextId(refType.get(childNode.getType()));

						XbRefObj refObj = new XbRefObj();
						refObj.setRef_type(refType.get(childNode.getType()));
						refObj.setRef_id(refID);
						refObj.setRef_name(childNodeName);
						refObj.setCreation_date(new Date());
						refDao.insert(refObj);
						insertFlag = 2;
				}	}

				if(childNodeName.indexOf("<" + SCHEMAREF + ">") != -1
						|| childNodeName.indexOf("<" + LINKBASEREF + ">") != -1
						|| childNodeName.indexOf("<" + ROLEREF + ">") != -1
						|| childNodeName.indexOf("<" + ARCROLEREF + ">") != -1) {
					insertFlag = 1;
				}

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