package com.sap.dbmtk.demo;

import java.awt.Color;
import java.awt.Component;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.SimpleDateFormat;

import javax.swing.table.JTableHeader;
import javax.swing.table.TableModel;

import org.jdesktop.swingx.JXTableHeader;
import org.jdesktop.swingx.decorator.ColorHighlighter;
import org.jdesktop.swingx.decorator.ComponentAdapter;
import org.jdesktop.swingx.decorator.HighlightPredicate;
import org.jdesktop.swingx.renderer.DefaultTableRenderer;
import org.jdesktop.swingx.renderer.StringValue;

import com.sap.dbmtk.demo.ui.GTable;
import com.sap.dbmtk.demo.ui.ResultSetTableModel;
import com.sap.dbmtk.demo.ui.focusabletip.FocusableTip;
import com.sap.dbmtk.demo.utils.Configuration;


public class ResultSetTable
extends GTable
{
	private static final long serialVersionUID = 1L;

	private boolean           _tabHeader_useFocusableTips   = true;
	private boolean           _cellContent_useFocusableTips = true;
	private FocusableTip      _focusableTip                 = null;
	private DataPanelAbstract _dataPanel                    = null;

	private final static Color NULL_VALUE_COLOR = new Color(240, 240, 240);

	public ResultSetTable(DataPanelAbstract dataPanel)
	{
		super();
		_dataPanel = dataPanel;

		// Reset renderer for BigDecimal, GTable formated it in a little different way
		setDefaultRenderer(BigDecimal.class, null);
		
		// TimeStamp format
		final String timestampFormat = Configuration.getCombinedConfiguration().getProperty("ResultSetTable.cellRenderer.format.Timestamp");
		if (timestampFormat != null)
		{
			@SuppressWarnings("serial")
			StringValue sv = new StringValue() 
			{
//				DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM);
				DateFormat df = new SimpleDateFormat(timestampFormat);
				@Override
				public String getString(Object value) 
				{
					return df.format(value);
				}
			};
			setDefaultRenderer(java.sql.Timestamp.class, new DefaultTableRenderer(sv));
		}

		// Date format
		final String dateFormat = Configuration.getCombinedConfiguration().getProperty("ResultSetTable.cellRenderer.format.Date");
		if (dateFormat != null)
		{
			@SuppressWarnings("serial")
			StringValue sv = new StringValue() 
			{
				DateFormat df = new SimpleDateFormat(dateFormat);
				@Override
				public String getString(Object value) 
				{
					return df.format(value);
				}
			};
			setDefaultRenderer(java.sql.Date.class, new DefaultTableRenderer(sv));
		}

		// Time format
		final String timeFormat = Configuration.getCombinedConfiguration().getProperty("ResultSetTable.cellRenderer.format.Time");
		if (timeFormat != null)
		{
			@SuppressWarnings("serial")
			StringValue sv = new StringValue() 
			{
				DateFormat df = new SimpleDateFormat(timeFormat);
				@Override
				public String getString(Object value) 
				{
					return df.format(value);
				}
			};
			setDefaultRenderer(java.sql.Time.class, new DefaultTableRenderer(sv));
		}

		// NULL Values: SET BACKGROUND COLOR
		addHighlighter( new ColorHighlighter(new HighlightPredicate()
		{
			@Override
			public boolean isHighlighted(Component renderer, ComponentAdapter adapter)
			{
				// Check NULL value
				String cellValue = adapter.getString();
				if (cellValue == null || ResultSetTableModel.DEFAULT_NULL_REPLACE.equals(cellValue))
					return true;
				
				// Check ROWID Column
				int mcol = adapter.convertColumnIndexToModel(adapter.column);
				String colName = adapter.getColumnName(mcol);
				if (mcol == 0 && ResultSetTableModel.ROW_NUMBER_COLNAME.equals(colName))
					return true;

				return false;
			}
		}, NULL_VALUE_COLOR, null));
	}

	@Override
	public Class<?> getColumnClass(int column)
	{
		if (getRowCount() == 0)
			return Object.class;

		Object o = getValueAt(0, column);
		Class<?> clazz = o!=null ? o.getClass() : Object.class;
		return clazz;
//		if (o instanceof Timestamp)
//			return Object.class;
//		else
//			return clazz;
//		Class clazz = super.getColumnClass(column);;
//		System.out.println("getColumnClass(col="+column+"): "+clazz.getName());
//		return clazz;
	}

	// 
	// TOOL TIP for: TABLE HEADERS
	//
	@Override
	protected JTableHeader createDefaultTableHeader()
	{
		return new JXTableHeader(getColumnModel())
		{
			private static final long serialVersionUID = 1L;

			@Override
			public String getToolTipText(MouseEvent e)
			{
				// Now get the column name, which we point at
				Point p = e.getPoint();
				int index = getColumnModel().getColumnIndexAtX(p.x);
				if ( index < 0 )
					return null;
				
				TableModel tm = getModel();
				if (tm instanceof ResultSetTableModel)
				{
					ResultSetTableModel rstm = (ResultSetTableModel) tm;
					String tooltip = rstm.getToolTipTextForTableHeader(index);

					if (_tabHeader_useFocusableTips)
					{
						if (tooltip != null) 
						{
							if (_focusableTip == null) 
								_focusableTip = new FocusableTip(this);

							_focusableTip.toolTipRequested(e, tooltip);
						}
						// No tool tip text at new location - hide tip window if one is
						// currently visible
						else if (_focusableTip != null) 
						{
							_focusableTip.possiblyDisposeOfTipWindow();
						}
						return null;
					}
					else
						return tooltip;
				}
				return null;
			}
		};
	}

	// 
	// TOOL TIP for: CELL DATA
	//
	@Override
	public String getToolTipText(MouseEvent e)
	{
		String tooltip = null;
		Point p = e.getPoint();
		int vrow = rowAtPoint(p);
		int vcol = columnAtPoint(p);
		if ( vrow >= 0 && vcol >= 0 )
		{
			int mcol = super.convertColumnIndexToModel(vcol);
			int mrow = super.convertRowIndexToModel(vrow);

			TableModel tm = getModel();
			if (tm instanceof ResultSetTableModel)
			{
				ResultSetTableModel rstm = (ResultSetTableModel) tm;
//				int sqlType = rstm.getSqlType(col);
//
//				int type = 0;
//				if (sqlType == Types.LONGVARBINARY || sqlType == Types.VARBINARY || sqlType == Types.BLOB)
//					type = 1;
//				else if (sqlType == Types.LONGVARCHAR || sqlType == Types.CLOB)
//					type = 2;
//				
//				if (type != 0)
//				{
//					Object cellValue = tm.getValueAt(row, col);
//					if (cellValue == null)
//						return null;
//					String cellStr   = cellValue.toString();
//
//					byte[] bytes = type == 2 ? cellStr.getBytes() : StringUtil.hexToBytes(cellStr);
//
//					tooltip = getContentSpecificToolTipText(cellStr, bytes);
//				}
				
				tooltip = _dataPanel.getTableToolTipText(rstm, mrow, mcol);

				if (_cellContent_useFocusableTips)
				{
					if (tooltip != null) 
					{
						if (_focusableTip == null) 
							_focusableTip = new FocusableTip(this);

						_focusableTip.toolTipRequested(e, tooltip);
					}
					// No tool tip text at new location - hide tip window if one is currently visible
					else if (_focusableTip != null) 
					{
						_focusableTip.possiblyDisposeOfTipWindow();
					}
					return null;
				}
				else
					return tooltip;

			} // end: ResultSetTableModel
//			else
//			{
//				String colName = tm.getColumnName(col);
//				Object cellValue = tm.getValueAt(row, col);
//			}
		}

		return tooltip;
	}
}
