package hiro.yoshioka.sql.resource;

import hiro.yoshioka.util.SQLDataType;
import hiro.yoshioka.util.StringUtil;

import java.nio.charset.Charset;
import java.sql.DatabaseMetaData;
import java.util.Collection;

public class DBColumn extends DBResource implements IDBColumn {
	private static final long serialVersionUID = 9999846456L;

	public enum SearchableType {
		SEARCHABLE_INVISIBLE, SEARCHABLE_VISIBLE, UNSEARCHABLE;

		public boolean isVisible() {
			return !SEARCHABLE_INVISIBLE.equals(this);
		}

		public boolean isSearchable() {
			return !UNSEARCHABLE.equals(this);
		}
	}

	int maxColumnNameLength;
	private SearchableType usingCondition = SearchableType.SEARCHABLE_VISIBLE;

	public static transient Object image;
	private String fAlias;
	private boolean onClickable;

	private int size;

	private SQLDataType dataType = SQLDataType.UNKNOWN;

	private String dataTypeString;

	private int decimalDigits;

	private boolean notnull;

	private boolean pkey;

	private boolean indexColumn;

	// -1はプロシジャ以外
	private short columnType = -1;

	public DBColumn(IDBColumn column) {
		super(column);
	}

	public DBColumn(IDBTable table) {
		super(table);
	}

	public int getSize() {
		return size;
	}

	public String getSizeString() {
		StringBuilder buf = new StringBuilder();
		buf.append(getSize());
		if (hasDecimalDigits()) {
			buf.append(",").append(decimalDigits);
		}
		return buf.toString();
	}

	public boolean isIndex() {
		return false;
		// return ((DBTable) _parent).hasIndex(this);
	}

	public int getDecimalDigits() {
		return decimalDigits;
	}

	@Override
	public boolean hasDecimalDigits() {
		return this.decimalDigits > 0;
	}

	@Override
	public boolean isOnClickable() {
		return onClickable;
	}

	public void setOnClickable(boolean onClickable) {
		this.onClickable = onClickable;
	}

	public boolean isNotNull() {
		return notnull;
	}

	public void setDecimalDigits(int decimalDigits) {
		this.decimalDigits = decimalDigits;
	}

	public void setNotNull(boolean notnull) {
		this.notnull = notnull;
	}

	public void setSize(int size) {
		this.size = size;
	}

	public void setDataType(SQLDataType dataType) {
		this.dataType = dataType;
	}

	public void setPKey(boolean pkey) {
		this.pkey = pkey;
	}

	public void setPKey(Collection<String> pkeyCollection) {
		if (pkeyCollection == null) {
			return;
		}
		if (pkeyCollection.contains(this.getName())) {
			setPKey(true);
			return;
		}
		for (String str : pkeyCollection) {
			if (super.name.equalsIgnoreCase(str)) {
				setPKey(true);
				return;
			}
		}

	}

	public boolean isPkey() {
		return pkey;
	}

	public boolean isIndexColumn() {
		return indexColumn;
	}

	public void setIndexColumn(boolean value) {
		indexColumn = value;
	}

	/*
	 * 
	 */
	public static String cnvColumnType(short type) {
		switch (type) {
		case DatabaseMetaData.procedureColumnIn:
			return "\u24be\u24dd";
		case DatabaseMetaData.procedureColumnInOut:
			return "\u24be\u24c4";
		case DatabaseMetaData.procedureColumnOut:
			return "\u24c4\u24e3";
		case DatabaseMetaData.procedureColumnResult:
			return "\u24c7\u24e2";
		case DatabaseMetaData.procedureColumnReturn:
			return "\u24c7\u24e3";
		case DatabaseMetaData.procedureColumnUnknown:
			return "\u24ca\u24da";
		default:
			return "";
		}
	}

	public String toString() {
		if (-1 != columnType) {
			return cnvColumnType(getColumnType()) + " " + getName() + " "
					+ getDataTypeString() + "(" + getSizeString() + ")";
		} else {
			if (getComment().length() == 0) {
				return getName() + " " + getDataTypeString() + "("
						+ getSizeString() + ")";
			}
			return getName() + " " + getDataTypeString() + "("
					+ getSizeString() + ") 【" + getComment() + "】";
		}
	}

	/**
	 * コンテンツアシスト用文字列返却。 fASTExpr==null?getName():fASTExpr
	 * 
	 * @return アシスト用文字列
	 */
	public String getProposalString() {
		return getName();
	}

	public String toStringWithIndexInfo() {
		return toString();// + " " + ((DBTable) _parent).getIndexNames(this);
	}

	public String getNameWithCommentLimLen(Charset charset) {
		return getNameWithAsComment(charset, this.maxColumnNameLength);
	}

	public String getNameWithAsComment() {
		return getNameWithAsComment(Charset.defaultCharset());
	}

	public String getNameWithAsComment(Charset charset) {
		return getNameWithAsComment(charset, this.maxColumnNameLength);
	}

	public void setComment(String remarks) {
		this.comment = remarks;
	}

	/**
	 * VARCHER,TIMESTAMP
	 */
	public SQLDataType getDataType() {
		return dataType;
	}

	public void setColumnType(short columnType) {
		this.columnType = columnType;
	}

	public short getColumnType() {
		return columnType;
	}

	/**
	 * @param short1
	 */
	public void setNullable(short short1) {
		notnull = (DatabaseMetaData.columnNoNulls == short1);
	}

	public boolean contain(String pattern) {
		if (getParent() != null) {
			if (getParent().getName().equalsIgnoreCase(pattern)
					|| getParent().getComment().equalsIgnoreCase(pattern)) {
				return true;
			}
		}
		if (containKeyInNameOrComment(pattern.toUpperCase())) {
			return true;
		}
		return false;
	}

	public String getAlias() {
		return fAlias == null ? "" : fAlias;
	}

	public String getImageString() {
		String key = this.getClass().toString();
		if (isPkey()) {
			return "\u24ab";
		} else if (isNotNull()) {
			return "\u24a9";
		} else {
			return "";
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * hiro.yoshioka.sql.resource.IAliasExtention#setAlias(java.lang.String)
	 */
	public void setAlias(String alias) {
		fAlias = alias;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see hiro.yoshioka.sql.resource.IDBTable#hasAlias()
	 */
	public boolean hasAlias() {
		return getAlias().length() > 0;
	}

	public Object getImage() {
		return image;
	}

	public String getUAlias() {
		return getAlias().toUpperCase();
	}

	public int getMaxColumnNameLength() {
		return maxColumnNameLength;
	}

	public void setMaxColumnNameLength(int maxColumnNameLength) {
		this.maxColumnNameLength = maxColumnNameLength;
	}

	public boolean isColumnIn() {
		return DatabaseMetaData.procedureColumnIn == columnType;
	}

	public boolean isColumnInOut() {
		return DatabaseMetaData.procedureColumnInOut == columnType;
	}

	public boolean isColumnOut() {
		return DatabaseMetaData.procedureColumnOut == columnType;
	}

	public boolean isColumnReturn() {
		return DatabaseMetaData.procedureColumnReturn == columnType;
	}

	public String getDataTypeString() {
		return dataTypeString;
	}

	public void setDataTypeString(String dataTypeString) {
		this.dataTypeString = dataTypeString;
	}

	public void setConditionParameter(SearchableType usingCondition) {
		this.usingCondition = usingCondition;
	}

	public SearchableType getSearchableType() {
		return usingCondition;
	}

	@Override
	public String getDefaultConditionValue() {
		return StringUtil.EMPTY_STRING;
	}
}