package daruma.storage_manager.type_definition;

import daruma.storage_manager.type_definition.TypeDefinition;
import daruma.storage_manager.type_definition.TypedInstance;
import daruma.storage_manager.type_definition.TypeException;
import daruma.storage_manager.StorageManager;
import daruma.storage_manager.ElementInfo;
import daruma.geometry.TransformationContext;
import daruma.sql.SQLDataType;
import daruma.sql.TableColumn;
import daruma.sql.TableColumnDefinition;
import daruma.xml.UniversalName;
import daruma.xml.SimpleXPath;
import daruma.xml.util.ElementUtil;
import daruma.util.Pair;
import daruma.util.LogWriter;

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

import java.util.List;
import java.util.ArrayList;


public abstract class AbstractMultiColumnSingleTypeDefinition
							extends TypeDefinition
{
	public	AbstractMultiColumnSingleTypeDefinition()
	{
		super( false , true );
	}

	@Override
	public	final	SQLDataType	getSingleSQLDataType()
	{
		return null;
	}

	@Override
	public	abstract List<TableColumnDefinition>
					getCompositeSQLDataType
						  ( StorageManager  storage ,
						    SimpleXPath  path ,
						    ElementInfo  elementInfo )
							throws TypeException;

	public	abstract List<String>	parseValue( String  value )
							throws TypeException;

	@Override
	public	abstract	int	convertToXMLElement
					( Element  element ,
					  Document  doc ,
					  StorageManager  storage ,
					  TransformationContext  trans ,
					  List<TableColumn>  columns ,
					  int  index ,
					  long  id )
						  throws TypeException;


	@Override
	public	final	Pair<TypedInstance, Integer>
				createInstance( Element  element ,
						ElementName  topLevelElement ,
						SimpleXPath  path ,
						StorageManager  storage ,
						int  elementIndex )
							throws TypeException
	{
		LogWriter.qwrite("DEBUG",  this.getClass().getName(),
				 ": createInstance()" );

		List<String>	values = null;

		try
		{
			values = this.parseValue
				 ( ElementUtil
				   .getChildNodesWholeText( element ) );
		}
		catch( TypeException  e )
		{
			throw new TypeException
				( "invalid element "
				  + element.getLocalName()
				  + " in namespace "
				  + element.getNamespaceURI()
				  + ": " + e.getMessage() , e );
		}


		SimpleXPath	newPath = path;

		if ( path != null )
		{
			newPath = new SimpleXPath( path );

			newPath.add( new UniversalName
				     ( element.getNamespaceURI() ,
				       element.getLocalName() ) );
		}


		List<TableColumnDefinition>	columnDefinitionList;
		try
		{
			columnDefinitionList
			  = this.getCompositeSQLDataType
			    ( storage , newPath, null );
		}
		catch( TypeException  e )
		{
			throw e;
		}

		if ( columnDefinitionList.size() == 0
		  || columnDefinitionList.size() != values.size() )
		{
			throw new TypeException( "internal error in "
						 + this.getClass().getName()
						 + ": unexpected array size" );
		}


		List<TableColumn>  columnList = new ArrayList<TableColumn>();

		for( int  i = 0  ;  i < columnDefinitionList.size()  ;  ++ i )
		{
			columnList.add( new TableColumn
					( columnDefinitionList.get(i) ,
					  values.get(i) ) );
		}

		return( new Pair<TypedInstance, Integer>
			( new TypedInstance( columnList , this ) ,
			  elementIndex + 1 ) );
	}
}
