package signals.JET;

import java.io.IOException;

import ncsa.hdf.hdf5lib.exceptions.*;
import signals.Signal;
import descriptors.JET.PPFDesc;

/**
 * A PPF Signal - Specifically a dataType.
 * 
 * All PPF Data should be stored and returned as floats.
 * 
 * 
 * @author oliford <codes@oliford.co.uk>
 */
public class PPF extends Signal {
	
	/** Load a JPF Object from a HDF5 cache file */
	public PPF(String cacheRoot, PPFDesc desc) throws IOException {
		super(cacheRoot + desc.path() + ".hdf");
		this.desc = desc;
	}
			
	/** Create a new 2D PPF directly from data*/
	public PPF(PPFDesc desc, Object data, Object xVec, Object tVec){
		super(data, new Object[]{ xVec, tVec });
		this.desc = desc;
	}
	
	/** Create a new 1D PPF (tVector) directly from data */
	public PPF(PPFDesc desc, Object data, Object tVec){
		super(data, new Object[]{ tVec });
		this.desc = desc;
	}
	
	/** PPF Location descriptor */
	private PPFDesc desc;
	
	/* Units of the data value */
	private String dataUnits;
	
	/* Comment of dataType */
	private String comment;
	
	/* Status flag */
	private int systemStatus;
	private int userStatus;

	@Override
	public final PPFDesc getDescriptor() { return desc; }
	
	/** Return vector of time coordinates */ 
	public final Object getTVector(){ return getCoords(getRank()-1); }
	
	/** Return vector of X coordinates */
	public final Object getXVector(){ return getCoords(0); }

	/** Return vector of time coordinates */ 
	public final Object getTVectorAsType(Class <?>type){ return getCoordsAsType(getRank()-1, type); }
	
	/** Return vector of X coordinates */
	public final Object getXVectorAsType(Class <?>type){ return getCoordsAsType(0, type); }

	/** Check this is a 1D PPF and get data */
	public final Object get1DData(){
		if(getRank() == 1)
			return getData();
		else
			throw new RuntimeException("Not a 1D PPF!");
	}
	
	/** Check this is a 2D PPF and get data */
	public final Object get2DData(){
		if(getRank() == 2)
			return getData();
		else
			throw new RuntimeException("Not a 2D PPF!");
	}
	
	@Override
	protected void writeExtraToHDF5(int file_id) throws IOException, HDF5Exception {
		super.writeExtraToHDF5(file_id);
		
		/* Just write the info as 0D data types, we could use attributes in theory, but then
		 * we already have nice util functions for this*/
		if(comment != null) writeHD5DataSpace(file_id, "Comment", 1, new long[]{1}, comment, TYPE_STRING);
		if(dataUnits != null) writeHD5DataSpace(file_id, "Units", 1, new long[]{1}, dataUnits, TYPE_STRING);
		writeHD5DataSpace(file_id, "SystemStatus", 1, new long[]{1}, new int[]{ systemStatus }, TYPE_INT);
		writeHD5DataSpace(file_id, "UserStatus", 1, new long[]{1}, new int[]{ userStatus }, TYPE_INT);
	}

	@Override
	protected void readExtraFromHDF5 (int file_id) throws IOException, HDF5Exception {		
		super.readExtraFromHDF5(file_id);
		
		try{ comment = readHDF5SingleString(file_id, "Comment"); }catch(HDF5Exception e){ comment = null; } 
		try{ dataUnits = readHDF5SingleString(file_id, "Units"); }catch(HDF5Exception e){ dataUnits = null; }
		systemStatus = readHDF5SingleInt(file_id, "SystemStatus");
		userStatus = readHDF5SingleInt(file_id, "UserStatus");
		
	}
	
	@Override
	public String toString() {
		return "PPF from '"+desc.toString()+"': " + super.toString() + 
		"; dataUnits='"+dataUnits+"'; " +
		"sysStat="+systemStatus+"; " +
		"usrStat="+userStatus+"; " +
		"comment = '"+comment+"';";
	}

	public final int getSystemStatusFlag() {	return systemStatus;  }
	public final void setSystemStatusFlag(int status) {	this.systemStatus = status;	}
	public final int getUserStatusFlag() {	return userStatus;  }
	public final void setUserStatusFlag(int status) {	this.userStatus = status;	}
	public final String getDataUnits() { return dataUnits; }
	public final void setDataUnits(String dataUnits) { this.dataUnits = dataUnits; }
	public final String getComment() { return comment; }
	public final void setComment(String comment) { this.comment = comment; }

	
}
