package hiro.yoshioka.sql.resource.view;

import hiro.yoshioka.sql.params.ConnectionProperties;
import hiro.yoshioka.sql.resource.DBColumn;
import hiro.yoshioka.sql.resource.DBConstraint;
import hiro.yoshioka.sql.resource.DBCrossRefference;
import hiro.yoshioka.sql.resource.DBIndexRoot;
import hiro.yoshioka.sql.resource.DBResource;
import hiro.yoshioka.sql.resource.DBRoot;
import hiro.yoshioka.sql.resource.DBSchema;
import hiro.yoshioka.sql.resource.IDBColumn;
import hiro.yoshioka.sql.resource.IDBSchema;
import hiro.yoshioka.sql.resource.IDBSequence;
import hiro.yoshioka.sql.resource.IDBTable;
import hiro.yoshioka.sql.resource.IDBTrigger;
import hiro.yoshioka.sql.resource.RecentryUsedResource;
import hiro.yoshioka.sql.resource.evernote.EvernoteTag;
import hiro.yoshioka.sql.resource.notes.NotesDBSchema;
import hiro.yoshioka.util.ImageUtil;
import hiro.yoshioka.util.SQLDataType;
import hiro.yoshioka.util.StringUtil;

import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.jface.viewers.StyledCellLabelProvider;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.jface.viewers.StyledString.Styler;
import org.eclipse.jface.viewers.ViewerCell;

public class DBTreeLabelProvider extends StyledCellLabelProvider {
	protected transient Log fLogger = LogFactory.getLog(getClass());
	boolean isResource;
	boolean isType;
	private Styler ERROR_STYLE, HYPERLINK_STYLE;

	public DBTreeLabelProvider(String columnName) {
		isResource = DBResourceTreeViewer.HEADER_NAME[0].equals(columnName);
		isType = DBResourceTreeViewer.HEADER_NAME[1].equals(columnName);
		ERROR_STYLE = StyledString.createColorRegistryStyler("ERROR_COLOR",
				null);
		HYPERLINK_STYLE = StyledString.createColorRegistryStyler(
				"ACTIVE_HYPERLINK_COLOR", null);
	}

	private void doResource(ViewerCell cell) {
		Object element = cell.getElement();

		StyledString styledString = null;
		if (element instanceof ConnectionProperties) {
			ConnectionProperties prop = (ConnectionProperties) element;
			styledString = new StyledString(prop.getDisplayString());
			styledString.append("(" + prop.getHost() + ")",
					StyledString.COUNTER_STYLER);
			if (prop.isConnected()) {
				cell.setImage(ImageUtil.getImage(ImageUtil.ACTION_32_CONNECT));
			} else {
				cell.setImage(ImageUtil
						.getImage(ImageUtil.ACTION_33_DISCONNECT));
			}
		} else if (element instanceof RecentryUsedResource) {
			RecentryUsedResource prop = (RecentryUsedResource) element;
			styledString = new StyledString(prop.getName(),
					StyledString.COUNTER_STYLER);
		} else if (element instanceof DBResource) {
			DBResource resource = (DBResource) element;

			if (resource instanceof DBRoot) {
				styledString = new StyledString(resource.getName());
				cell.setImage(ImageUtil
						.getImage(ImageUtil.DBRESOURCE_01_DATABASE));
			} else if (resource instanceof DBConstraint) {
				styledString = new StyledString(
						((DBConstraint) resource).toString());
				String decoration = resource.getImageString();
				styledString.append(decoration, StyledString.COUNTER_STYLER);
			} else if (resource instanceof IDBColumn) {
				DBColumn obj = (DBColumn) resource;
				if (-1 != obj.getColumnType()) {
					String t = obj.cnvColumnType(obj.getColumnType()) + " "
							+ obj.getName() + " ";
					styledString = new StyledString(t);
					String decoration = obj.getDataTypeString() + "("
							+ obj.getSizeString() + ")";
					styledString
							.append(decoration, StyledString.COUNTER_STYLER);
				} else {
					String t = obj.getName() + " ";
					if (obj.isPkey()) {
						styledString = new StyledString(t, ERROR_STYLE);
					} else if (obj.isNotNull()) {
						Styler styler = StyledString.createColorRegistryStyler(
								"ACTIVE_HYPERLINK_COLOR", null);
						styledString = new StyledString(t, HYPERLINK_STYLE);
					} else {
						styledString = new StyledString(t);
					}
					if (obj.getComment().length() > 0) {
						String decoration = "(" + obj.getComment() + ")";
						styledString.append(decoration,
								StyledString.COUNTER_STYLER);
					}
				}
				SQLDataType dataType = obj.getDataType();
				if (dataType.isDateOrDateTimeOrTime()) {
					cell.setImage(ImageUtil
							.getImage(ImageUtil.DBRESOURCE_50_DATE));
				} else if (dataType.isString()) {
					cell.setImage(ImageUtil
							.getImage(ImageUtil.DBRESOURCE_51_LABEL));
				} else if (dataType.isBlob() || dataType.isBinary()) {
					cell.setImage(ImageUtil
							.getImage(ImageUtil.DBRESOURCE_52_GENERIC_REG));
				} else if (dataType.isNumerics()) {
					cell.setImage(ImageUtil
							.getImage(ImageUtil.DBRESOURCE_53_NUMBER));
				} else {
					cell.setImage(ImageUtil
							.getImage(ImageUtil.DBRESOURCE_54_COLUMN));
				}
			} else if (resource instanceof IDBTable) {
				IDBTable table = (IDBTable) resource;
				StringBuilder tableString = new StringBuilder();
				if (!table.isValid()) {
					tableString.append("\u2620 ");
				}
				if ((table.isFunction() || table.isProcudeure())
						&& table.getCatalog().length() > 0) {
					tableString.append(table.getCatalog()).append(".");
				}
				tableString.append(table.getNameWithAsComment());
				styledString = new StyledString(tableString.toString());
				if (table.isView()) {
					cell.setImage(ImageUtil
							.getImage(ImageUtil.DBRESOURCE_04_VIEW));
				} else if (table.isFunction()) {
					cell.setImage(ImageUtil
							.getImage(ImageUtil.DBRESOURCE_08_FUNCTION));
				} else if (table.isTable()) {
					cell.setImage(ImageUtil
							.getImage(ImageUtil.DBRESOURCE_03_TABLE));
				} else if (table.isFunction()) {
					cell.setImage(ImageUtil
							.getImage(ImageUtil.DBRESOURCE_04_VIEW));
				} else if (table.isProcudeure()) {
					cell.setImage(ImageUtil
							.getImage(ImageUtil.DBRESOURCE_06_PROCEDURE));
				} else if (table.isSynonym()) {
					cell.setImage(ImageUtil
							.getImage(ImageUtil.DBRESOURCE_07_SYNONYM));
				}
			} else if (resource instanceof IDBTrigger) {
				IDBTrigger trigger = (IDBTrigger) resource;
				if (!trigger.isValid()) {
					styledString = new StyledString("\u2620 "
							+ trigger.toString());
				} else {
					styledString = new StyledString(trigger.toString());
				}
				cell.setImage(ImageUtil
						.getImage(ImageUtil.DBRESOURCE_05_TRIGGER));
			} else if (resource instanceof DBCrossRefference) {
				styledString = new StyledString(
						((DBCrossRefference) resource).toString());
				String decoration = resource.getImageString();
				styledString.append(decoration, StyledString.COUNTER_STYLER);
			} else if (resource instanceof DBSchema) {
				IDBSchema schema = (IDBSchema) resource;
				styledString = new StyledString(resource.getName());
				if (schema.isCurrent() || schema.isDefault()) {
					String decoration = String.format(" [%s]",
							schema.getCurrentDefaultString());
					styledString.append(decoration,
							StyledString.QUALIFIER_STYLER);
				}
				cell.setImage(ImageUtil
						.getImage(ImageUtil.DBRESOURCE_02_SCHEMA));
			} else if (resource instanceof IDBSequence) {
				styledString = new StyledString(resource.getName());
				cell.setImage(ImageUtil
						.getImage(ImageUtil.DBRESOURCE_80_SEQUENCE));
			} else if (resource instanceof DBIndexRoot) {
				styledString = new StyledString("INDEX");
				styledString.append("(" + resource.childrenNum() + ")",
						StyledString.COUNTER_STYLER);
				cell.setImage(ImageUtil.getImage(ImageUtil.DBRESOURCE_55_INDEX));
			} else if (resource instanceof EvernoteTag) {
				EvernoteTag eTag = (EvernoteTag) resource;
				styledString = new StyledString(eTag.getName());
				String decoration = String.format(" (%d)", eTag.getNoteCount());
				styledString.append(decoration, StyledString.QUALIFIER_STYLER);
				cell.setImage(ImageUtil.getImage(ImageUtil.DBRESOURCE_EV_TAG));
			} else {
				styledString = new StyledString(resource.getName());
			}

		} else {
			styledString = new StyledString("Unknown element");
		}
		cell.setText(styledString.toString());
		cell.setStyleRanges(styledString.getStyleRanges());
	}

	private void doType(ViewerCell cell) {
		Object element = cell.getElement();

		StyledString styledString = null;
		if (element instanceof ConnectionProperties) {
			ConnectionProperties prop = (ConnectionProperties) element;

			int r = prop.getRequestCount();
			int e = prop.getEndOfRequestCount();
			if (r == 0) {
				styledString = new StyledString(StringUtil.EMPTY_STRING);
			} else {
				if (r == e) {
					styledString = new StyledString(String.format(
							"Req:%d (End:%d)", r, e));
				} else {
					styledString = new StyledString(String.format("Req:%d ", r));
					styledString.append(String.format("(End:%d)", e),
							StyledString.QUALIFIER_STYLER);
				}
			}
		} else if (element instanceof RecentryUsedResource) {
			RecentryUsedResource prop = (RecentryUsedResource) element;
			styledString = new StyledString(String.format("%d/%d",
					prop.childrenNum(), prop.getSizeOfRecentryUsedResources()),
					styledString.COUNTER_STYLER);
		} else if (element instanceof DBResource) {
			DBResource resource = (DBResource) element;

			if (resource instanceof DBRoot) {
				styledString = new StyledString(StringUtil.EMPTY_STRING);
			} else if (resource instanceof IDBColumn) {
				DBColumn obj = (DBColumn) resource;
				styledString = new StyledString(StringUtil.nvl(obj
						.getDataTypeString()));

				String decoration = String.format("(%s)", obj.getSizeString());
				styledString.append(decoration, StyledString.QUALIFIER_STYLER);

				if (obj.isPkey()) {
					decoration = String.format(" [PK]");
					styledString.append(new StyledString(decoration,
							ERROR_STYLE));
				} else if (obj.isNotNull()) {
					decoration = String.format(" [NN]");
					styledString.append(new StyledString(decoration,
							HYPERLINK_STYLE));
				}
			} else if (resource instanceof IDBTable) {
				IDBTable table = (IDBTable) resource;
				if (table.isFunction() || table.isProcudeure()) {
					styledString = new StyledString(table.getProcedureType()
							.getTypeString());
				} else {
					styledString = new StyledString(StringUtil.EMPTY_STRING);
				}
			} else if (resource instanceof IDBSchema) {
				IDBSchema schema = (IDBSchema) resource;
				if (schema instanceof NotesDBSchema) {
					Properties p = schema.getProperties();
					styledString = new StyledString(StringUtil.nvl(p
							.getProperty("filePath")));
				} else {
					styledString = new StyledString(String.format("%d Objects",
							schema.childrenNum()));
				}
			} else {
				styledString = new StyledString(StringUtil.EMPTY_STRING);
			}

		} else {
			styledString = new StyledString("Unknown type");
		}
		cell.setText(styledString.toString());
		cell.setStyleRanges(styledString.getStyleRanges());
	}

	public void update(ViewerCell cell) {

		if (isResource) {
			doResource(cell);
		} else if (isType) {
			doType(cell);
		}

		super.update(cell);
	}
}