package prolog.implementation;

import java.util.*;
import prolog.model.*;
import prolog.util.*;
import prolog.*;

/**
 * <p>AbstractStatement has methods for reordering a relation after a
 * given format</p>
 */
public abstract class AbstractStatement
	extends
		Fact
	implements
		IStatement
{
	/**
	 * constructor 1
	 */
	public AbstractStatement( int name )
	{
		super( name );
	}

	/**
	 * constructor 2
	 */
	public AbstractStatement( int name, IRelation r )
	{
		super( name, r );
	}

	/**
	 * generates a new fact matching the format of the given statement
	 * @param f - the fact to be taken the values from
	 * @param srcRelationFormat - the format of the given fact
	 * @param targetStatement - the statement for which the new fact is created for
	 * @return a new fact formated for the targetStatement
	 */
	protected Fact generateFact( IFact f, Map factFormat, IStatement targetStatement )
		throws ParameterMatchingError
	{
		return (Fact)
			SingletonFactory.getBuilder().createFact(
				targetStatement.getName(),
				generateRelation(
					f,
					factFormat,
					targetStatement ) );
	}

	/**
	 * <p>builds a new relation from the given fact
	 * matching the format of the targetStatement.</p>
	 * <p>create new relation</p>
	 * <p>iterate over atoms of relation of statement2</p>
	 * <p>search for atom value int factmap and get index in fact f</p>
	 * <p>fetch atom from fact f at index and add atom found to new relation</p>
	 * @param f = ?-statement1(batman,robin).
	 * @param factFormat = [X]=[0],[Y]=[1]
	 * @param targetStatement statement1(X,Y):-statement2(Y,X).
	 * @return (robin,batman)</p>
	 */
	protected Relation generateRelation( IFact f, Map factFormat, IStatement targetStatement )
		throws ParameterMatchingError
	{
		Relation back = (Relation) SingletonFactory.getBuilder().createRelation();
		//try
		{
			IRelation targetRelation = targetStatement.getRelation();
			Iterator target = targetRelation.getValues();

			while( target.hasNext() )
			{
				Object targetParameter = target.next();
				Integer indexInSrcRel = (Integer) factFormat.get( targetParameter );
				if( indexInSrcRel != null )
				{
					back.add( f.getRelation().get( indexInSrcRel.intValue() ) );
				}
				else
				{
					back.add( new Variable(((Value)targetParameter).getName()) );
				}
			}
		}
		//catch( Throwable t )
		{
			//t.printStackTrace();
			//System.exit( -69 );
		}
		return back;
	}
}
