/*
   Project: UL

   Copyright (C) 2005 Michael Johnston & Jordi Villa-Freixa

   Author: Michael Johnston

   Created: 2005-06-02 15:34:11 +0200 by michael johnston

   This application is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This application is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU General Public
   License along with this library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
*/

#include "ULFramework/ULMatrix.h"

@implementation ULMatrix

- (int) Rows
{
	return [self numberOfRows];
}

- (int) Columns
{
	return [self numberOfColumns];
}

- (void) setRows: (int) rows
{
	numberOfRows = rows;
}

- (void) setColumns: (int) columns
{
	numberOfColumns = columns;
}

/*******
NSCoding Methods
********/

//Retaining this implementation of NSCoding methods
//to maintain backwards compatibility with non-keyed coding
//of old ULMatrix objects. This compatibility will probably
//have to be broken at some stage.

- (id) initWithCoder: (NSCoder*) decoder
{	
	int i,j;
	int matrixElements;
	int length, count;
	double *matrixStore;
	NSMutableArray* matrixRow;
	NSNumber *element;

	if([decoder allowsKeyedCoding])
	{
		matrix = [NSMutableArray arrayWithCapacity: 1];
		[matrix retain];
		numberOfRows = [decoder decodeIntForKey: @"Rows"];
		numberOfColumns = [decoder decodeIntForKey: @"Columns"];
		matrixStore = (double*)[decoder decodeBytesForKey: @"Matrix"
						returnedLength: &length];
		matrixElements = length/sizeof(double);
		for(i=0, count=0; i<numberOfRows; i++)
		{
			matrixRow = [NSMutableArray arrayWithCapacity: 1];
			for(j=0; j<numberOfColumns; j++)
			{
				element = [NSNumber numberWithDouble: matrixStore[count]];
				[matrixRow addObject: element];
				count++;
			}
			[matrix addObject: matrixRow];
		}

		columnHeaders = [decoder decodeObjectForKey: @"ColumnHeaders"];
		name = [decoder decodeObjectForKey: @"Name"];
		[columnHeaders retain];
		[name retain];
	}
	else
	{	
		matrix = [decoder decodeObject];
		numberOfRows = [matrix count];
		numberOfColumns = [[matrix objectAtIndex:0] count];
		columnHeaders = nil;
		name = nil;
	}

	return self;
}

//probably should encode types of each number as well

- (void) encodeWithCoder: (NSCoder*) encoder
{
	int i, j, bytesLength, count;
	double* matrixStore;
	id array;

	if([encoder allowsKeyedCoding])
	{
		bytesLength = numberOfRows*numberOfColumns*sizeof(double);
		matrixStore = (double*)malloc(numberOfRows*numberOfColumns*sizeof(double));
	
		for(i=0, count=0; i<numberOfRows; i++)
			for(j=0; j<numberOfColumns; j++)
			{
				matrixStore[count] = [[[matrix objectAtIndex: i] objectAtIndex: j] doubleValue]; 
				count++;
			}
		
		[encoder encodeBytes: (uint8_t*)matrixStore length: bytesLength forKey: @"Matrix"];
		[encoder encodeInt: numberOfRows forKey: @"Rows"];
		[encoder encodeInt: numberOfColumns forKey: @"Columns"];

		if(columnHeaders != nil)
			[encoder encodeObject: columnHeaders forKey: @"ColumnHeaders"];

		if(name != nil)
			[encoder encodeObject: name forKey: @"Name"];

		free(matrixStore);
	}
	else
	{
		[encoder encodeObject: matrix];
	}
}

@end
