
package jp.riken.brain.ni.samuraigraph.data;

import java.text.ParseException;
import java.util.Calendar;

import jp.riken.brain.ni.samuraigraph.base.SGData;
import jp.riken.brain.ni.samuraigraph.base.SGUtility;

/**
 *
 */
public class SGSXYDateData extends SGDateData
	implements SGISXYTypeData
{

	// a data object created with date information
	private SGSXYData mData = null;


	/**
	 * 
	 */
	public SGSXYDateData()
	{
		super();
	}


	/**
	 * 
	 */
	public SGSXYDateData(
		final String[] dateArray, final double[] yValueArray ) throws ParseException
	{
		this( dateArray, yValueArray, null, null, null );
	}


	/**
	 * 
	 */
	public SGSXYDateData(
		final String[] dateArray, final double[] yValueArray, final String[] labelArray ) throws ParseException
	{
		this( dateArray, yValueArray, null, null, labelArray );
	}


	/**
	 * 
	 */
	public SGSXYDateData(
		final String[] dateArray,
		final double[] yValueArray,
		final double[] lowerErrorArray,
		final double[] upperErrorArray ) throws ParseException
	{
		this( dateArray, yValueArray, lowerErrorArray, upperErrorArray, null );
	}


	/**
	 * 
	 */
	public SGSXYDateData(
		final String[] dateArray,
		final double[] yValueArray,
		final double[] lowerErrorArray,
		final double[] upperErrorArray,
		final String[] labelArray ) throws ParseException
	{
		super( dateArray );

		if( yValueArray.length!=dateArray.length )
		{
			throw new IllegalArgumentException("yValueArray.length!=dateArray.length");
		}

		if( lowerErrorArray!=null & upperErrorArray!=null )
		{
			if( lowerErrorArray.length!=dateArray.length )
			{
				throw new IllegalArgumentException("lowerErrorArray.length!=dateArray.length");
			}

			if( upperErrorArray.length!=dateArray.length )
			{
				throw new IllegalArgumentException("upperErrorArray.length!=dateArray.length");
			}
		}
		
		if( labelArray!=null )
		{
			if( labelArray.length!=dateArray.length )
			{
				throw new IllegalArgumentException("labelArray.length!=dateArray.length");
			}
		}

		final double[] xValueArray = this.calcXValueArray();
		final String[] stringArray = labelArray!=null ? SGUtility.copyStringArray( labelArray ) : SGUtility.copyStringArray( dateArray );
		this.mData = new SGSXYData( xValueArray, yValueArray, lowerErrorArray, upperErrorArray, stringArray );
	}


	/**
	 * 
	 */
	public SGSXYDateData(
		final int[] yearArray, final int[] monthArray, final int[] dateArray,
		final double[] yValueArray )
	{
		this( yearArray, monthArray, dateArray, null, null, yValueArray );
	}


	/**
	 * 
	 */
	public SGSXYDateData(
		final int[] yearArray, final int[] monthArray, final int[] dateArray,
		final double[] yValueArray,
		final double[] lowerErrorArray, final double[] upperErrorArray )
	{
		super( yearArray, monthArray, dateArray );

		if( yValueArray==null )
		{
			throw new IllegalArgumentException("yValueArray==null");
		}

		if( yValueArray.length!=yearArray.length )
		{
			throw new IllegalArgumentException("yValueArray.length!=yearArray.length");
		}

		if( lowerErrorArray!=null & upperErrorArray!=null )
		{
			if( lowerErrorArray.length!=yearArray.length )
			{
				throw new IllegalArgumentException("lowerErrorArray.length!=yearArray.length");
			}

			if( upperErrorArray.length!=yearArray.length )
			{
				throw new IllegalArgumentException("upperErrorArray.length!=yearArray.length");
			}
		}

		final double[] xValueArray = this.calcXValueArray();
		final String[] stringArray = this.getStringArray( yearArray, monthArray, dateArray );
		this.mData = new SGSXYData( xValueArray, yValueArray, lowerErrorArray, upperErrorArray, stringArray );
	}


//	/**
//	 * 
//	 */
//	public SGSXYCalendarData(
//		final int[] yearArray, final int[] monthArray, final int[] dateArray,
//		final double[][] yValueArray )
//	{
//		super( yearArray, monthArray, dateArray );
//
//		if( yValueArray==null )
//		{
//			throw new IllegalArgumentException("yValueArray==null");
//		}
//
//		if( yValueArray.length!=yearArray.length )
//		{
//			throw new IllegalArgumentException("yValueArray.length!=yearArray.length");
//		}
//
//		final double[] xValueArray = this.calcXValueArray();
//		this.mData = new SGSXYMultipleData( xValueArray, yValueArray );
//	}


	// calculate x values
	private double[] calcXValueArray()
	{
		final InnerDate[] dArray = this.mDateArray;
		final int num = dArray.length;
		final double[] xValueArray = new double[num];
		final Calendar cal = Calendar.getInstance();
		final int ratio = 1000*3600*24;
		for( int ii=0; ii<num; ii++ )
		{
			final InnerDate d = dArray[ii];
			cal.set( d.year, d.month, d.date );
			xValueArray[ii] = cal.getTimeInMillis()/ratio;
		}

		return xValueArray;
	}


	// returns the array of text strings
	private String[] getStringArray(
		final int[] yearArray, final int[] monthArray, final int[] dateArray )
	{
		final String[] stringArray = new String[yearArray.length];
		for( int ii=0; ii<stringArray.length; ii++ )
		{
			stringArray[ii] = yearArray[ii] + "/" + monthArray[ii] + "/" + dateArray[ii];
		}
		return stringArray;
	}


	/**
	 * 
	 */
	public int getPointsNumber()
	{
		return this.mData.getPointsNumber();
	}


	/**
	 * Returns the name of data type.
	 * @return
	 */
	public String getDataType()
	{
		return SGDataTypeConstants.SXY_DATE_DATA;
	}


	/**
	 * Set data.
	 * @param data - data set to this object
	 */
	public boolean setData( final SGData data )
	{
		if( !(data instanceof SGSXYDateData) )
		{
			throw new IllegalArgumentException("!(data instanceof SGSXYCalendarData)");
		}
		
		if( super.setData( data) == false )
		{
			return false;
		}

		SGSXYDateData dData = (SGSXYDateData)data;
		this.mData = (SGSXYData)dData.mData.copy();

		return true;
	}


	/**
	 * 
	 */
	public double getMinValueX()
	{
		return this.mData.getMinValueX();
	}


	/**
	 * 
	 */
	public double getMaxValueX()
	{
		return this.mData.getMaxValueX();
	}


	/**
	 * 
	 */
	public double getMinValueY()
	{
		return this.mData.getMinValueY();
	}


	/**
	 * 
	 */
	public double getMaxValueY()
	{
		return this.mData.getMaxValueY();
	}


	/**
	 * Returns the x value with the given index.
	 * @param n - index
	 * @return x-value with the given index
	 */
	public Double getXValue( final int n )
	{
		return this.mData.getXValue(n);
	}


	/**
	 * Returns the y value with the given index.
	 * @param n - index
	 * @return y-value with the given index
	 */
	public Double getYValue( final int n )
	{
		return this.mData.getYValue(n);
	}


	/**
	 * Returns the lower error value with the given index if it exists.
	 * @param n - index
	 * @return lower error value with the given index
	 */
	public Double getLowerErrorValue( final int n )
	{
		return this.mData.getLowerErrorValue(n);
	}


	/**
	 * Returns the upper error value with the given index if it exists.
	 * @param n - index
	 * @return upper error value with the given index
	 */
	public Double getUpperErrorValue( final int n )
	{
		return this.mData.getUpperErrorValue(n);
	}



	/**
	 * Returns the string with the given index if it exists.
	 * @param n - index
	 * @return a string with the given index
	 */
	public String getString( final int n )
	{
		return this.mData.getString(n);
	}


	/**
	 * Returns a copy of x-value array.
	 * @return x-value array
	 */
	public double[] getXValueArray()
	{
		return this.mData.getXValueArray();
	}


	/**
	 * Returns a copy of y-value array.
	 * @return y-value array
	 */
	public double[] getYValueArray()
	{
		return this.mData.getYValueArray();
	}


	/**
	 * Returns a copy of lower-error-value array if they exist.
	 * @return lower-error-value array
	 */
	public double[] getLowerErrorValueArray()
	{
		return this.mData.getLowerErrorValueArray();
	}


	/**
	 * Returns a copy of upper-error-value array if they exist.
	 * @return upper-error-value array
	 */
	public double[] getUpperErrorValueArray()
	{
		return this.mData.getUpperErrorValueArray();
	}


	/**
	 * Returns a copy of string array if they exist.
	 * @return string array
	 */
	public String[] getStringArray()
	{
		return this.mData.getStringArray();
	}


	/**
	 * Returns whether this data has error values.
	 * @return whether this data has error values
	 */
	public boolean isErrorValueHolding()
	{
		return this.mData.isErrorValueHolding();
	}


	/**
	 * Returns whether this data has strings.
	 * @return whether this data has strings
	 */
	public boolean isStringArrayHolding()
	{
		return this.mData.isStringArrayHolding();
	}



	/**
	 * 
	 */
	public void dispose()
	{
		super.dispose();
		
		// do not dispose mData because it can be shared with
		// other data objects
		
		this.mData = null;
	}


	// main method
	public static void main( String[] args ) throws Exception
	{
		String[] xArray = {
			"2005/1/1",
			"2005/2/1",
			"2005/3/1",
			"2005/4/1",
			"2005/5/1",
			"2005/6/1",
			"2005/7/1",
			"2005/8/1",
			"2005/9/1",
			"2005/10/1",
			"2005/11/1",
			"2005/12/1",
			"2006/1/1"
		};

		double[] yArray = {
			3.1,
			8.0,
			1.4,
			2.5,
			5.8,
			6.3,
			10.8,
			3.4,
			4.1,
			8.5,
			6.8,
			9.5,
			7.3
		};

		double[] lArray = new double[xArray.length];
		double[] uArray = new double[xArray.length];

		SGSXYDateData d = new SGSXYDateData( xArray, yArray, lArray, uArray );

		SGSXYData dataSXY = (SGSXYData)d.mData;
		double[] xArray_ = dataSXY.getXValueArray();
		double[] yArray_ = dataSXY.getYValueArray();
		String[] sArray_ = dataSXY.getStringArray();
		for( int ii=0; ii<xArray_.length; ii++ )
		{
			System.out.println( xArray[ii] + "  " + (long)xArray_[ii] + "  "+ yArray_[ii] + "  " + sArray_[ii] );
			if( ii!=xArray_.length-1 )
			{
				System.out.println( (long)( xArray_[ii+1] - xArray_[ii] )/(3600*24*1000) );
			}
		}
		System.out.println();
	}

}

