package daruma.geometry;

import daruma.geometry.CoordinateSystem;
import daruma.geometry.DrmPoint;

import daruma.geometry.TransformationException;
import daruma.geometry.TransformationErrorException;

public class AffineCoordinateSystemTransformation
    extends CoordinateSystemTransformation
{
    private double[][] matrix;

    public AffineCoordinateSystemTransformation( String identifier,
						 CoordinateSystem sourceCS,
						 CoordinateSystem targetCS ,
						 double[][] matrix )
    {
	super( identifier , sourceCS , targetCS );

	this.matrix = matrix.clone();
    }

    public double[][] getMatrix()
    {
	return this.matrix;
    }

    @Override
    public String getTransformName()
    {
	return "affine";
    }

    @Override
    public String encode()
    {
	StringBuilder buf = new StringBuilder();

	for ( int i = 0 ; i < this.matrix.length ; ++ i )
	{
	    for ( int j = 0 ; j < this.matrix[i].length ; ++ j )
	    {
		if ( i != 0 || j != 0 )
		{
		    buf.append( " " );
		}

		buf.append( this.matrix[i][j] );
	    }
	}

	return buf.toString();
    }


    @Override
    public DrmPoint transform( DrmPoint point ) throws TransformationException
    {
	if ( point.getDimension() != this.matrix.length )
	{
	    throw new TransformationException( "dimension mismatch" );
	}

	// XXX
	assert point.getDimension() == 2; 

	int dim = point.getDimension();

	double[] org = new double[dim + 1];
	org[0] = point.getX();
	org[1] = point.getY();
	org[2] = 1.0;

	double[] ret = new double[dim];

	for ( int axis = 0 ; axis < point.getDimension() ; ++ axis )
	{
	    ret[axis] = 0.0;

	    for ( int i = 0 ; i < dim + 1 ; ++ i )
	    {
		ret[axis] += this.matrix[axis][i] * org[i];

		System.err.println( "ret[" + axis+ "] += "
				    + this.matrix[axis][i] + " * "
				    + org[i] );
	    }
	}

	return new DrmPoint( ret[0] , ret[1] );
    }
}
