package asandatabasebrowser.model;

import java.util.ArrayList;
import java.sql.*;

import net.sourceforge.swingx.SxTextUtilities;

/**
 * テーブル情報<<entity>>
 */
public class TableInfo implements ITableInfo {
	final String tableCatalog;	// テーブルカタログ (null の可能性がある)
	final String tableSchema;	// テーブルスキーマ (null の可能性がある)
	final String tableName;	// テーブル名 
	final String tableType;	// テーブルタイプ。
								// 典型的なタイプは、"TABLE"、"VIEW"、"SYSTEM TABLE"、
								// "GLOBAL TEMPORARY"、"LOCAL TEMPORARY"、"ALIAS", "SYNONYM" である 
	String remarks;		// テーブルに関する説明 
	public final VvDatabase db;
	/** ArrayList<ColumnInfo> */
	ArrayList columnInfoList = null;
	/** プライマリキーの一覧 ArrayList<String> nullable */
	public ArrayList pkList = null;
	
	public TableInfo(
				VvDatabase db,
				String tableCatalog,
				String tableSchema,
				String tableName,
				String tableType,
				String remarks,
				ArrayList columnInfoList) {
		assert db != null;
		assert tableName != null;
		assert tableType != null;
		
		this.db = db;
		this.tableCatalog = tableCatalog;
		this.tableSchema  = tableSchema;
		this.tableName    = tableName;
		this.tableType    = tableType;
		this.remarks      = remarks;
		this.columnInfoList = columnInfoList;
	}
	public String getCatalogName() { return tableCatalog; }
	public String getSchemaName() { return tableSchema; }
	public String getTableName() { return tableName; }
	public String getTableType() { return tableType; }
	public String getRemarks() { return remarks; }
	public void updateColumnInfoList() throws DbException {
		if (columnInfoList == null) {
			columnInfoList = db.getColumnInfoList(tableCatalog, tableSchema, tableName);
			pkList = db.getPrimaryKeyList(tableCatalog, tableSchema, tableName);
		}
	}
	public ArrayList getColumnInfoList() {
//		if (columnInfoList == null) {
//			columnInfoList = db.getColumnInfoList(tableCatalog, tableSchema, tableName);
//		}
		return columnInfoList;
	}
	public int getColumnCount() { return getColumnInfoList().size(); }
	public IColumnInfo getIColumnInfo(int index) { return getColumnInfo(index); }
	public ColumnInfo getColumnInfo(int index) {
		return (ColumnInfo) getColumnInfoList().get(index);
	}
	public int getColumnIndexByName(String name) {
		ArrayList list = getColumnInfoList();
		for (int i=0; i<list.size(); i++) {
			ColumnInfo info = (ColumnInfo) list.get(i);
			if (name.equalsIgnoreCase(info.columnName)) {
				return i;
			}
		}
		return -1;	// 見つからない
	}
	public String getColumnName(int index) {
		ColumnInfo info = (ColumnInfo) getColumnInfoList().get(index);
		return info.columnName;
	}
//	public String getTitleName() {
//		// どういうやり方がいいのかな？
//		String title = tableName;
//		if (tableSchema != null) title = tableSchema+"."+title;
//		if (tableCatalog != null) title = tableCatalog+"."+title;
//		if (remarks != null && remarks.length() > 0) {
//			title += "(" + remarks + ")";
//		}
//		return title;
//	}
	public VvDatabase getDatabase() { return db; }
	/**
	 * SQLで使用するテーブル名を返す。
	 * スキーマ名、あるいはカタログ名を付与する。
	 * 引用符をサポートする場合は引用符もつける。
	 */
	public String getSqlTableName() {
		try {
			// 引用符がある場合
			String q = db.getMetaData().getIdentifierQuoteString();
			if (q != null && q.length() > 0) {
				if (tableSchema!=null && tableSchema.length()>0) return q+tableSchema+q+"."+q+tableName+q;
				if (tableCatalog!=null && tableCatalog.length()>0) return q+tableCatalog+q+"."+q+tableName+q;
				return q+tableName+q;
			}
			// 引用符をサポートする場合
			if (db.getMetaData().supportsMixedCaseQuotedIdentifiers()) {
				if (tableSchema!=null && tableSchema.length()>0) return tableSchema+".\""+tableName+"\"";
				if (tableCatalog!=null && tableCatalog.length()>0) return tableCatalog+".\""+tableName+"\"";
				return "\""+tableName+"\"";
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		// 引用符をサポートしない場合
		if (tableSchema!=null && tableSchema.length()>0) return tableSchema+"."+tableName;
		if (tableCatalog!=null && tableCatalog.length()>0) return tableCatalog+"."+tableName;
		return tableName;
	}

	public boolean equals(Object obj) {
		if (! (obj instanceof TableInfo)) return false;
		TableInfo info = (TableInfo) obj;
		if(SxTextUtilities.compareString(tableCatalog, info.tableCatalog)!=0) return false;
		if(SxTextUtilities.compareString(tableSchema,  info.tableSchema )!=0) return false;
		if(SxTextUtilities.compareString(tableName,    info.tableName   )!=0) return false;
		if(SxTextUtilities.compareString(tableType,    info.tableType   )!=0) return false;
		return true;
	}
	public Object[] createDefaultRecord() {
		Object[] result = new Object[columnInfoList.size()];
		for (int i=0; i<columnInfoList.size(); i++) {
			result[i] = getColumnInfo(i).columnDefault;
		}
		return result;
	}
	/**
	 * プライマリキーの順番を返す.
	 * @return	プライマリキーの順番(1,2,3...) (-1)のときにはPKではない。
	 */
	public int getPrimaryKeySeq(String colname) {
		assert colname != null;
		if (pkList == null) return -1;
		for (int i=0; i<pkList.size(); i++) {
			if (colname.compareTo((String) pkList.get(i)) == 0) {
				return i+1;
			}
		}
		return -1;
	}

	public String toString() {
//		return 
//			"tableCatalog = "+tableCatalog + "\n"+
//			"tableSchema  = "+tableSchema + "\n"+
//			"tableName = "+tableName + "\n"+
//			"tableType = "+tableType + "\n" +
//			"remarks = "+remarks+"\n"+
//			"columnInfoList = "+columnInfoList;
		return tableName;
	}
}


