package daruma.wfs.filter;

import daruma.wfs.filter.PredicateDescription;
import daruma.wfs.filter.predicates.IntegratedPredicateDescription;

import daruma.storage_manager.StorageManager;
import daruma.storage_manager.type_definition.TypeName;
import daruma.storage_manager.type_definition.TypeDefinition;

import daruma.geometry.TransformationContext;

import daruma.xml.util.XMLParseErrorException;
import daruma.xml.util.ElementUtil;
import daruma.xml.util.PrefixMap;
import daruma.xml.Lexicon;

import daruma.xml.URI;

import org.w3c.dom.Element;
import java.util.List;


public class FilterParser
{
	private	FilterParser()
	{
	}

	public static PredicateDescription
			      parseFilter
			      ( Element  filterElement ,
				TypeName  typeName ,
				TypeDefinition  type ,
				TransformationContext  trans ,
				StorageManager  storage ,
				PrefixMap  prefixMap )
		throws XMLParseErrorException
	{
		/* <<< [06/10/16 15:34 I.Noda] <<< */
		//if ( ! filterElement.getLocalName().equals( "Filter" ) ) {
		//	throw new XMLParseErrorException
		//	    ( "Filter tag expected, found "
		//	      + filterElement.getLocalName()
		//	      + " in namespace "
		//	      + filterElement.getNamespaceURI()
		//	      + "." );
		//}
		/* === [06/10/16 15:34 I.Noda] === */
		Lexicon.MispFilter.matchesOrXmlException
			(filterElement, "in GetFeature/Query") ;
		/* >>> [06/10/16 15:34 I.Noda] >>> */

		List<Element>	filterContentElements
				= ElementUtil.getChildElements
						    ( filterElement );

		if ( filterContentElements.size() == 0 )
		{
			throw new XMLParseErrorException
				  ( "Filter tag doesn't have"
				    + " child element,"
				    + " filter specification not found" );
		}
		else if ( filterContentElements.size() >= 2 )
		{
			throw new XMLParseErrorException
				  ( "too many filter specifications, "
				    + "Filter tag must only have"
				    + " one child element" );
		}

		Element	filter = filterContentElements.get( 0 );

		if ( filter.getNamespaceURI() == null
		  || ! filter.getNamespaceURI().equals( URI.MISP ) )
		{
			throw new XMLParseErrorException
				  ( "filter \"" + filter.getLocalName() + "\""
				    + " does not in namespace " + URI.MISP );
		}


		//
		// Handle Predicates
		//
		if ( IntegratedPredicateDescription
		     .isAcceptablePredicate( filter.getLocalName() ) )
		{
			return( new IntegratedPredicateDescription
				( filter , typeName, type , trans ,
				  storage ) );
		}
		else if ( filter.getLocalName().equals( "PropertyIsBetween" )
		       || filter.getLocalName().equals( "PropertyIsLike" )
		       || filter.getLocalName().equals( "PropertyIsNull" ) )
		{
			// XXX: not implemented yet
			throw new XMLParseErrorException
			  ( "sorry, filter \"" + filter.getLocalName() + "\""
			    + " has not implemented yet" );
		}
		else if ( filter.getLocalName().equals( "DWinthin" )
		       || filter.getLocalName().equals( "Beyond" ) )
		{
			// XXX: not supported yet
			throw new XMLParseErrorException
			  ( "sorry, filter \"" + filter.getLocalName() + "\""
			    + " has not supported yet" );
		}
		else
		{
			throw new XMLParseErrorException
				( "cannot handle filter \""
				  + filter.getLocalName() + "\"" );
		}
	}
}
