package imagej.dataset;

import imagej.MetaData;
import imagej.data.Type;

import java.util.ArrayList;

//TODO - our convention is that indexing subsets moves right to left

public class CompositeDataset implements Dataset, RecursiveDataset
{
	private Dataset parent;
	private ArrayList<Dataset> subsets;
	private Type type;
	private int[] dimensions;

	public CompositeDataset(Type type, int[] dimensions, ArrayList<Dataset> subsets)
	{
		this.type = type;
		this.dimensions = dimensions;
		this.subsets = subsets;
		this.parent = null;
		for (Dataset subset : this.subsets)
			subset.setParent(this);
	}
	
	@Override
	public int[] getDimensions()
	{
		return this.dimensions;
	}
	
	@Override
	public Type getType()
	{
		return this.type;
	}

	@Override
	public MetaData getMetaData()
	{
		// TODO - do something
		return null;
	}
	
	@Override
	public void setMetaData(MetaData metadata)
	{
		// TODO - do something
	}
	
	@Override
	public double getDouble(int[] index, int axis)
	{
		RecursiveDataset subset = (RecursiveDataset) getSubset(index[axis]); 
		return subset.getDouble(index, axis-1);
	}

	@Override
	public void setDouble(int[] index, int axis, double value)
	{
		RecursiveDataset subset = (RecursiveDataset) getSubset(index[axis]); 
		subset.setDouble(index, axis-1, value);
	}

	@Override
	public boolean isComposite()
	{
		return true;
	}

	@Override
	public Dataset getParent()
	{
		return this.parent;
	}

	@Override
	public void setParent(Dataset dataset)
	{
		this.parent = dataset;
	}

	@Override
	public Object getData()
	{
		return null;
		// throw new IllegalArgumentException("CompositeDatasets do not support getting data array");
	}

	@Override
	public void setData(Object data)
	{
		throw new IllegalArgumentException("CompositeDatasets do not support setting data array");
	}

	@Override
	public void releaseData()
	{
		// not necessary to do anything
	}
	
	@Override
	public Dataset insertNewSubset(int position)
	{
		if (this.parent != null)
			throw new IllegalArgumentException("can only add subsets to outermost Dataset");

		int[] subsetDimensions = this.dimensions.clone();
		
		subsetDimensions[position] = 1;
		
		Dataset ds = new PlanarDatasetFactory().createDataset(this.type, subsetDimensions);
		
		ds.setParent(this);
		
		this.subsets.add(position, ds);
		
		int outermostAxis = this.dimensions.length - 1;
		
		this.dimensions[outermostAxis]++;
		
		return ds;
	}

	@Override
	public Dataset removeSubset(int position)
	{
		if (this.parent != null)
			throw new IllegalArgumentException();
		
		Dataset ds = this.subsets.remove(position);
		
		ds.setParent(null);
		
		int outermostAxis = this.dimensions.length - 1;
		
		this.dimensions[outermostAxis]--;

		return ds;
	}

	@Override
	public Dataset getSubset(int position)
	{
		return this.subsets.get(position);
	}

	@Override
	public double getDouble(int[] position)
	{
		if (this.parent != null)
			throw new IllegalArgumentException();

		int outermostAxis = this.dimensions.length - 1;
		
		return getDouble(position, outermostAxis);
	}

	@Override
	public void setDouble(int[] position, double value)
	{
		if (this.parent != null)
			throw new IllegalArgumentException();
		
		int outermostAxis = this.dimensions.length - 1;

		setDouble(position, outermostAxis, value);
	}

	@Override
	public Dataset getSubset(int[] partialIndex, int axis)
	{
		if (axis < 0)
			throw new IllegalArgumentException("axis index ("+axis+") less than 0");

		RecursiveDataset nextSubset = (RecursiveDataset)getSubset(partialIndex[axis]);
		
		if (axis == 0)
			return (Dataset) nextSubset;
		
		return nextSubset.getSubset(partialIndex, axis-1);
	}

	@Override
	public Dataset getSubset(int[] index)
	{
		int outermostAxis = index.length - 1;

		return getSubset(index, outermostAxis);
	}
	
}

@@ -249,105 +249,133 @@
 ate 
-Dataset parent;%0A%09private ArrayList%3CDataset%3E subsets;%0A%09private Type type;%0A%09private int%5B%5D dimension
+Type type;%0A%09private int%5B%5D dimensions;%0A%09private Dataset parent;%0A%09private MetaData metadata;%0A%09private ArrayList%3CDataset%3E subset
 s;%0A%0A
@@ -559,16 +559,40 @@
 = null;%0A
+%09%09this.metadata = null;%0A
 %09%09for (D
@@ -840,44 +840,28 @@
 %7B%0A%09%09
-// TODO - do something%0A%09%09return null
+return this.metadata
 ;%0A%09%7D
@@ -927,30 +927,33 @@
 %7B%0A%09%09
-// TODO - do something
+this.metadata = metadata;
 %0A%09%7D%0A
@@ -2114,24 +2114,32 @@
 imensions = 
+new int%5B
 this.dimensi
@@ -2146,52 +2146,117 @@
 ons.
-clone();%0A%09%09%0A%09%09subsetDimensions%5Bposition%5D = 1
+length-1%5D;%0A%09%09%0A%09%09for (int i = 0; i %3C subsetDimensions.length; i++)%0A%09%09%09subsetDimensions%5Bi%5D = this.dimensions%5Bi%5D
 ;%0A%09%09
@@ -2969,32 +2969,49 @@
  position)%0A%09%7B%0A%09%09
+// WRONG????%0A%09%09//
 if (this.parent 
@@ -3013,32 +3013,34 @@
 rent != null)%0A%09%09
+//
 %09throw new Illeg
@@ -3230,24 +3230,41 @@
 value)%0A%09%7B%0A%09%09
+// WRONG????%0A%09%09//
 if (this.par
@@ -3270,32 +3270,34 @@
 rent != null)%0A%09%09
+//
 %09throw new Illeg

fix a couple bugs brought out through testing [insertNewSubset(), set/getMetaData()]