/*
 * 作成日: 2005/11/26
 */
package asandatabasebrowser.view;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.border.EmptyBorder;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;

import net.sourceforge.swingx.SxOptionPane;

import asandatabasebrowser.AsanDatabaseBrowser;
import asandatabasebrowser.model.DbException;
import asandatabasebrowser.model.TableInfo;



/**
 * レコード件数を[欽ちゃん仮装大賞]のように表示するダイアログ.
 */
public class DbCountDialog extends JDialog {
	Object[][] tableCount;	// [0] TableInfo [1] Integer
	JTable table;
	JButton closeButton;
	Thread thread = null;
	/**
	 * 
	 * @param parent
	 * @param db
	 * @param tableList	ArrayList<TableInfo>
	 */
	public DbCountDialog(Frame parent, ArrayList tableList) {
		super(parent, "count(*)");
		//this.tableList = tableList;
		// 各コンポーネントを作成する
		tableCount = new Object[tableList.size()][2];
		for (int i=0; i<tableList.size(); i++) {
			TableInfo t = (TableInfo) tableList.get(i);
			tableCount[i][0] = t;//Global.localization.filter(t.getTableName());
			tableCount[i][1] = "?";
		}
		table = new RitchTable(tableCount, new Object[] {"テーブル名", "レコード数"}) {
			public TableCellEditor getCellEditor(int row, int column) {
				return null;	// 編集不可。もっとエレガントな設定方法はないのかな？
			}
		};
		table.getTableHeader().setReorderingAllowed(false); // ドラッグは無効
		table.getColumnModel().getColumn(1).setCellRenderer(new CountRenderer());
		table.getTableHeader().addMouseListener(new DbTableHeaderMouseListener());

		closeButton = new JButton("閉じる");
		closeButton.setToolTipText("件数を取得中に閉じてもいいよ");
		// レイアウトする
		JPanel panel = (JPanel) getContentPane();
		panel.setBorder(new EmptyBorder(20,20,20,20));
		panel.setLayout(new BorderLayout());
		panel.add(new JScrollPane(table), BorderLayout.CENTER);
		JPanel button_panel = new JPanel();
		button_panel.add(closeButton);
		panel.add(button_panel, BorderLayout.SOUTH);
		getRootPane().setDefaultButton(closeButton);
		thread = new Thread(new CountThread());
		thread.start();
		closeButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				setVisible(false);
				thread = null;
			}
		});
		addWindowListener(new WindowAdapter() {
			public void windowClosed(WindowEvent e) {
				setVisible(false);
				thread = null;
			}
		});
	}
	/** 
	 * レコード件数を取得するスレッド 
	 */
	class CountThread implements Runnable {
		public void run() {
			for (int i = 0; i < tableCount.length; i++) {
				TableInfo t = (TableInfo) tableCount[i][0];
				try {
					int count = t.db.getRecordCount(t);
					// 本当はイベントスレッド以外からGUIの操作をするのはよくない
					table.setValueAt(new Integer(count), i, 1);
				} catch (DbException e) {
					table.setValueAt("取得失敗", i, 1);
					e.printStackTrace();
				}
				// 途中でダイアログを閉じたら処理を中断する。
				if (thread == null)
					break;
			}
			thread = null;
		}
	}
	/** 件数を右寄せにするためのレンダラ */
	class CountRenderer extends DefaultTableCellRenderer {
		/** セルを描画するのに使用されるコンポーネントを返します。*/ 
		public Component getTableCellRendererComponent(
				JTable table, Object value, 
				boolean isSelected, boolean hasFocus, int row, int column) {
			Component c = super.getTableCellRendererComponent(table, value, 
					isSelected, hasFocus, row, column);
			JLabel label = (JLabel) c;
			label.setHorizontalAlignment(JLabel.RIGHT);
			return c;
		}
	}
	
	/** クリックされたらソートを行う。*/
	class DbTableHeaderMouseListener extends MouseAdapter implements Comparator {
		int lastCol = -1;		// ソートを行うカラム
		boolean asc = false;	// 昇順/降順
		public void mouseClicked(MouseEvent e) {
			if (thread != null) {
				AsanDatabaseBrowser.theApp.showMessage(DbCountDialog.this,
						"件数取得中はソートできません", null,
						SxOptionPane.INFORMATION_MESSAGE);
				return;
			}
			//System.out.println(e);
			// 左ボタンがシングルクリックされたら
			if (e.getClickCount()==1 && (e.getModifiers()&MouseEvent.BUTTON1_MASK)!=0) {
				int col = table.getTableHeader().columnAtPoint(e.getPoint());
				//System.out.println("sort("+e.getX()+","+e.getY()+") col="+col);
				if (col == -1) return;
				if (col==lastCol) {
					asc = ! asc;
				}
				else {
					lastCol = col;
					asc = true;
				}
				Arrays.sort(tableCount, this);
				repaint();
			}
		}
		// Comparatorインターフェースのメソッド
		public int compare(Object o1, Object o2) {
			return asc ? compare0(o1, o2) : -compare0(o1, o2);
		}
		private int compare0(Object o1, Object o2) {
			Object[] rec1 = (Object[]) o1;
			Object[] rec2 = (Object[]) o2;
			Object fld1 = rec1[lastCol];
			Object fld2 = rec2[lastCol];
			if (fld1==fld2) return 0;
			if (fld1==null) return -1;
			if (fld2==null) return 1;
			if (fld1 instanceof Comparable) {
				Comparable c1 = (Comparable) fld1;
				Comparable c2 = (Comparable) fld2;
				if (c1.getClass().equals(c2.getClass())) {
					return c1.compareTo(c2);
				} else {
					// "取得失敗"のとき比較できないので、クラス名で比較する。
					return c1.getClass().getName().compareTo(c2.getClass().getName());
				}
			}
			if (lastCol == 0) {	// テーブル名で比較
				return fld1.toString().compareTo(fld2.toString());
			}
			System.out.println("比較できない型です "+fld1.getClass());
			return 0;
		}
		// Comparatorインターフェースのメソッド
		public boolean equals(Object obj) {
			return this==obj;
		}
	}	
}
