package daruma.storage_manager.type_definition.types;

import daruma.storage_manager.type_definition.AbstractMultiColumnSingleTypeDefinition;
import daruma.storage_manager.type_definition.TypeException;
import daruma.storage_manager.type_definition.ColumnNameFactory;

import daruma.storage_manager.StorageManager;
import daruma.storage_manager.StorageException;

import daruma.geometry.TransformationContext;

import daruma.xml.SimpleXPath;
import daruma.xml.util.WhitespaceProceccer;

import daruma.sql.TableColumnDefinition;
import daruma.sql.TableColumn;
import daruma.sql.SQLDataType;
import daruma.sql.SQLDataTypeConstant;

import daruma.util.ISO8601DateFormat;
import daruma.util.LogWriter;

import java.sql.Timestamp;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.w3c.dom.Element;
import org.w3c.dom.Text;
import org.w3c.dom.Document;



public class DateTimeTypeDefinition
		    extends AbstractMultiColumnSingleTypeDefinition
{
	/* !!! [06/08/16 19:12 I.Noda] !!! 
	 * カラム名の拡張部分の文字列定数
	 */
	final static public String ColNameSqlTimeSuffix = "_sql_" ;
	final static public String ColNameGmlTimeSuffix = "_gml_" ;

	public	DateTimeTypeDefinition()
	{
		super();
	}

	@Override
	public	List<String>	parseValue( String  value )
							throws TypeException
	{
		String	v = WhitespaceProceccer.cutoffEdgeWhitespaces( value );

		ISO8601DateFormat	f = new ISO8601DateFormat();

		try
		{
			f.parse( v );
		}
		catch( ParseException  e )
		{
			throw new TypeException
			( "\"" + value + "\" is not a valid dateTime value" );

		}


		List<String>	ret = new ArrayList<String>();
		ret.add( v );
		ret.add( v );

		return( ret );
	}

	@Override
	public	List<TableColumnDefinition>	getCompositeSQLDataType
						  ( StorageManager  storage ,
						    SimpleXPath  path )
							throws TypeException
	{
	    LogWriter.qwrite("DEBUG",  "In ", this.getClass().getName(),
			     ".getCompositeSQLDataType()" );
	    LogWriter.qwrite("DEBUG",  "path = [", path, "]" );

	    /* --------------------
	     * return value は最初は空リスト 
	     */
	    List<TableColumnDefinition>
		ret = new ArrayList<TableColumnDefinition>();

	    /* --------------------
	     * カラム名の本体の取得 
	     */
	    String colNameBody = null ;
	    if( path == null ) {
		/* top level element の場合 */
		colNameBody = 
		    ColumnNameFactory.getTopLevelElementColumnName() ;
	    } else {
		/* sub level element の場合 */
		SimpleXPath	newPath = new SimpleXPath( path );
		try {
		    colNameBody = storage.getShortXPathStringForDB( newPath );
		} catch( StorageException  ex ) {
		    throw new TypeException( ex );
		}
	    }

	    /* --------------------
	     * 補助カラムの生成
	     * 別の箇所で参照するため、順序が大事。
	     */
	    /* !!! [06/08/16 03:26 I.Noda] !!! 
	     * ColumnNameFactory による命名に統一
	     */
	    
	    /*
	    ret.add( new TableColumnDefinition
		     (ColumnNameFactory
		      .getColumnName(colNameBody,
				     this.ColNameSqlTimeSuffix),
		      new SQLDataType( "datetime" ,
				       Timestamp.class ) ) );
	    */
	    
	    ret.add( new TableColumnDefinition
		     ( colNameBody,
		       SQLDataTypeConstant.TIMESTAMP ) );

	    ret.add( new TableColumnDefinition
		     (ColumnNameFactory
		      .getColumnName(colNameBody,
				     this.ColNameGmlTimeSuffix),
		      SQLDataTypeConstant.BLOB ) );

	    return( ret );
	}


	@Override
	public	int	convertToXMLElement( Element  element ,
					     Document  doc ,
					     StorageManager  storage ,
					     TransformationContext  trans ,
					     List<TableColumn>  columns ,
					     int  index ,
					     long  id )
						    throws TypeException
	{
		LogWriter.qwrite( "DEBUG", this.getClass().getName(),
				  ".convertToXMLElement()" );

		if ( index + 1 >= columns.size() )
		{
			throw new TypeException
			  ( "internal error in " + this.getClass().getName()
			    + ": unexpected instantiation" );
		}


		String	value = columns.get( index + 1 ).getValue();
		LogWriter.qwrite( "DEBUG", this.getClass().getName(),
				  "convertToXMLElement():",
				  "value = ", value );

		if ( value != null )
		{
			Text	text = doc.createTextNode( value );

			element.appendChild( text );
		}

		return( index + 2 );
	}
}
