/*
 * 作成日: 2007/07/10
 */
package asandatabasebrowser.action;

import java.awt.event.ActionEvent;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.util.ArrayList;

import javax.swing.SwingUtilities;

import asandatabasebrowser.Global;
import asandatabasebrowser.AsanDatabaseBrowser;
import asandatabasebrowser.model.DbData;
import asandatabasebrowser.model.FavoriteTable;
import asandatabasebrowser.model.ResultSetInfo;
import asandatabasebrowser.model.TableInfo;
import asandatabasebrowser.model.VvDatabase;
import asandatabasebrowser.view.DbDatabaseDefinitionFrame;

import net.sourceforge.swingx.SxHeavyAction;
import net.sourceforge.swingx.SxOptionPane;
import net.sourceforge.swingx.SxProgressDialog;

/** テーブル定義を開く. */
public class OpenTableDefinitionAction extends SxHeavyAction {
	final AsanDatabaseBrowser tools;
	SxProgressDialog progressDialog;
	public OpenTableDefinitionAction(AsanDatabaseBrowser tools) {
		super("テーブル定義を開く");
		putValue(SHORT_DESCRIPTION, "テーブル定義を開きます");
		putValue(LONG_DESCRIPTION, "テーブル定義を開きます");
		putValue(SMALL_ICON, Global.getImageIcon("/resources/TableDefinition.png"));
		this.tools = tools;
	}
	public void actionPerformed(ActionEvent e) {
		// 選択されたテーブル情報を取得する。
		TableInfo tableInfo = null;
		int index = tools.getTreeFrame().tab.getSelectedIndex();
		if (index == 0) {
			Object obj = tools.getTreeFrame().getTree().getSelectionNodeObject();
			if (obj instanceof TableInfo) {
				tableInfo = (TableInfo) obj; 
			}
		} else {
			// 選択されたテーブルを取得する。DBに接続されていなければ
			Object obj = tools.getTreeFrame().getFavTree().getSelectionNodeObject();
			if (obj instanceof FavoriteTable) {
				FavoriteTable favtable = (FavoriteTable) obj;
//				try {
					VvDatabase db = tools.doc.getDatabaseFromFavorite(favtable);
					if (db == null) {
						tools.showMessage(tools.getTreeFrame(),
								"指定されたデータベースがありません。:"+favtable.dbName, null, 
								SxOptionPane.ERROR_MESSAGE);
						return;
					}
					if (db.getConnection() == null) {
						tools.showMessage(tools.getTreeFrame(),
								"データベースに接続されていません。:"+favtable.dbName, null, 
								SxOptionPane.ERROR_MESSAGE);
						return;
					}
					tableInfo = tools.doc.getTableInfoFromFavorite(favtable);
//				} catch (DbException ex) {
//					tools.showMessage(tools.getTreeFrame(),
//							"テーブルの情報の取得に失敗しました", ex, 
//							AsanDatabaseBrowser.ERROR_MESSAGE);
//					return;
//				}
			}
		}
		if (tableInfo == null) return;	// 選択されていないとき
		
		// 重い処理
		HeavyThread thread = new HeavyThread(tableInfo.db, tableInfo);
		progressDialog = new SxProgressDialog(tools.getTreeFrame(), 
    			"テーブル定義の取得", thread, 0, 12);		// 12個
    	progressDialog.start();
	}


	class HeavyThread extends Thread {
		TableInfo tableInfo;
		VvDatabase db;
		HeavyThread(VvDatabase db, TableInfo tableInfo) {
			assert db != null;
			assert tableInfo != null;
			this.db = db;
			this.tableInfo = tableInfo;
		}		
		public void run() {
			DatabaseMetaData meta = tableInfo.db.getMetaData();
			final ArrayList list = new ArrayList();

			int prog = 0;
	    	progressDialog.setProgress(prog++, "Column");
	    	if (progressDialog.isAbort()) return;
			try {
				ResultSet rs = meta.getColumns(tableInfo.getCatalogName(), tableInfo.getSchemaName(), 
						tableInfo.getTableName(), null);
				DbData data = new DbData(db.createResultSetInfo(rs), db.getRecordList(rs));
				list.add(new Object[] {"Column", data});
			} catch (Exception e) {
				list.add(new Object[] {"Column", e});
			}

	    	progressDialog.setProgress(prog++, "PrimaryKey");
	    	if (progressDialog.isAbort()) return;
			try {
				ResultSet rs = meta.getPrimaryKeys(tableInfo.getCatalogName(), tableInfo.getSchemaName(), 
						tableInfo.getTableName());
				DbData data = new DbData(db.createResultSetInfo(rs), db.getRecordList(rs));
				list.add(new Object[] {"PrimaryKey", data});
			} catch (Exception e) {
				list.add(new Object[] {"PrimaryKey", e});
			}

	    	progressDialog.setProgress(prog++, "ExportedKeys");
	    	if (progressDialog.isAbort()) return;
			try {
				ResultSet rs = meta.getExportedKeys(tableInfo.getCatalogName(), tableInfo.getSchemaName(), 
						tableInfo.getTableName());
				DbData data = new DbData(db.createResultSetInfo(rs), db.getRecordList(rs));
				list.add(new Object[] {"ExportedKeys", data});
			} catch (Exception e) {
				list.add(new Object[] {"ExportedKeys", e});
			}		

	    	progressDialog.setProgress(prog++, "ImportedKeys");
	    	if (progressDialog.isAbort()) return;
			try {
				ResultSet rs = meta.getImportedKeys(tableInfo.getCatalogName(), tableInfo.getSchemaName(), 
						tableInfo.getTableName());
				DbData data = new DbData(db.createResultSetInfo(rs), db.getRecordList(rs));
				list.add(new Object[] {"ImportedKeys", data});
			} catch (Exception e) {
				list.add(new Object[] {"ImportedKeys", e});
			}		

	    	progressDialog.setProgress(prog++, "Index");
	    	if (progressDialog.isAbort()) return;
			try {
				ResultSet rs = meta.getIndexInfo(tableInfo.getCatalogName(), tableInfo.getSchemaName(), 
						tableInfo.getTableName(), false, true);
				DbData data = new DbData(db.createResultSetInfo(rs), db.getRecordList(rs));
				list.add(new Object[] {"Index", data});
			} catch (Exception e) {
				list.add(new Object[] {"Index", e});
			}		

	    	progressDialog.setProgress(prog++, "TablePrivileges");
	    	if (progressDialog.isAbort()) return;
			try {
				ResultSet rs = meta.getTablePrivileges(tableInfo.getCatalogName(), tableInfo.getSchemaName(), 
						tableInfo.getTableName());
				DbData data = new DbData(db.createResultSetInfo(rs), db.getRecordList(rs));
				list.add(new Object[] {"TablePrivileges", data});
			} catch (Exception e) {
				list.add(new Object[] {"TablePrivileges", e});
			}		

	    	progressDialog.setProgress(prog++, "ColumnPrivileges");
	    	if (progressDialog.isAbort()) return;
			try {
				ResultSet rs = meta.getColumnPrivileges(tableInfo.getCatalogName(), tableInfo.getSchemaName(), 
						tableInfo.getTableName(), null);
				DbData data = new DbData(db.createResultSetInfo(rs), db.getRecordList(rs));
				list.add(new Object[] {"ColumnPrivileges", data});
			} catch (Exception e) {
				list.add(new Object[] {"ColumnPrivileges", e});
			}				

	    	progressDialog.setProgress(prog++, "BestRowIdentifier");
	    	if (progressDialog.isAbort()) return;
			try {
				// スコープの指定の仕方がわからない
				ResultSet rs = meta.getBestRowIdentifier(tableInfo.getCatalogName(), tableInfo.getSchemaName(), 
						tableInfo.getTableName(), DatabaseMetaData.bestRowTemporary, false);
				ArrayList list1 = db.getRecordList(rs);
				rs = meta.getBestRowIdentifier(tableInfo.getCatalogName(), tableInfo.getSchemaName(), 
						tableInfo.getTableName(), DatabaseMetaData.bestRowTransaction, false);
				ArrayList list2 = db.getRecordList(rs);
				list1.addAll(list2);
				rs = meta.getBestRowIdentifier(tableInfo.getCatalogName(), tableInfo.getSchemaName(), 
						tableInfo.getTableName(), DatabaseMetaData.bestRowSession, false);
				ArrayList list3 = db.getRecordList(rs);
				list1.addAll(list3);
				ResultSetInfo resultSetInfo = db.createResultSetInfo(rs);
				DbData data = new DbData(resultSetInfo, list1);
				list.add(new Object[] {"BestRowIdentifier", data});
			} catch (Exception e) {
				list.add(new Object[] {"BestRowIdentifier", e});
			}				

	    	progressDialog.setProgress(prog++, "VersionColumns");
	    	if (progressDialog.isAbort()) return;
			try {
				ResultSet rs = meta.getVersionColumns(tableInfo.getCatalogName(), tableInfo.getSchemaName(), 
						tableInfo.getTableName());
				DbData data = new DbData(db.createResultSetInfo(rs), db.getRecordList(rs));
				list.add(new Object[] {"VersionColumns", data});
			} catch (Exception e) {
				list.add(new Object[] {"VersionColumns", e});
			}			

			progressDialog.dispose();
			// イベントディスパッチスレッドでフォームを開く
			SwingUtilities.invokeLater(new Runnable() {
				public void run() {
					tools.openFrame(new DbDatabaseDefinitionFrame(
							//tableInfo.getTitleName(),
							tableInfo.getSqlTableName(),
							Global.getImage("/resources/TableDefinition.png"),
							list));
				}
			});
		}
	}
	public void updateStatus() {
		
	}
}
