/*------------------------------------------------------------------------------*
 * File Name:				 													*
 * Creation: 																	*
 * Purpose: OriginC Source C file												*
 * Copyright (c) ABCD Corp.	2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010		*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 *------------------------------------------------------------------------------*/

#include <Origin.h>
#include "IgorProFile.h"
#include <oExtFile.h>
#include "fu_utils.h"
#include <okocutils.h>



static int _igp_file_type(string strName)
{
	string strExt;
	int nPos = strName.ReverseFind('.');
	strExt = strName.Mid(nPos+1, strlen(strName)-nPos);
	if (0 == strExt.CompareNoCase("ibw"))
		return TYPE_IBW;
	else
		return TYPE_PXP;
}

void IgorProFile::IgorProFile(LPCSTR lpcszFileName)
{
	m_strFileName = lpcszFileName;
	m_type = _igp_file_type(m_strFileName);
}

int IgorProFile::Open(int nBaseOffset)
{
	m_nBaseOffset = nBaseOffset;
	m_nColIndex = 1;
	
	if(!Open(m_strFileName, file::modeRead|file::typeBinary|file::shareDenyWrite)){
		printf("Fail to load file : %s\n", m_strFileName);
		return IMPERR_FILE_OPEN;
	}
	
	byte bb;
	Read(&bb, 1);
	
	m_info.platform = bb?IGP_WIN:IGP_MAC;
	SeekToBegin();
	
	return 0;
	
}

int IgorProFile::GetVersion()
{
	return m_info.version;
}

int IgorProFile::GetDim()
{
	return m_info.dim;
}

int IgorProFile::GetType()
{
	return m_type;
}

#define IMPORT_TO_MATRIX(_FSI_, _TYPE_, _MODE_)	\
		{ml.SetInternalDataType(_FSI_);\
		Matrix<_TYPE_> mm(ml, nIndex);	\
		mm.SetSize(m_info.nDim[1], m_info.nDim[0]);	\
		return igp_read_data_m(&mm, this, m_nBaseOffset, &m_info, d2, d3, _MODE_);}

int IgorProFile::Import2Matrix(MatrixLayer &ml, int nIndex, int d2, int d3)
{
	if(m_info.type & NT_CMPLX)
		IMPORT_TO_MATRIX(FSI_COMPLEX, complex, 1)
	else if (m_info.type & NT_FP32)
		IMPORT_TO_MATRIX(FSI_REAL, float, 1)
	else if(m_info.type & NT_FP64)
		IMPORT_TO_MATRIX(FSI_DOUBLE, double, 1)
	else if((m_info.type & NT_UNSIGNED) && (m_info.type & NT_I8))
		IMPORT_TO_MATRIX(FSI_BYTE, byte, 1)
	else if((m_info.type & NT_UNSIGNED) && (m_info.type & NT_I16))
		IMPORT_TO_MATRIX(FSI_USHORT, unsigned short, 1)
	else if((m_info.type & NT_UNSIGNED) && (m_info.type & NT_I32))
		IMPORT_TO_MATRIX(FSI_ULONG, unsigned int, 1)
	else if(m_info.type & NT_I8)
		IMPORT_TO_MATRIX(FSI_CHAR, char, 1)
	else if(m_info.type & NT_I16)
		IMPORT_TO_MATRIX(FSI_SHORT, short, 1)
	else if(m_info.type & NT_I32)
		IMPORT_TO_MATRIX(FSI_LONG, int, 1)
	else
		ASSERT(false);
	
	return 1;
}


// Read the header information
int IgorProFile::ReadHeader(TreeNode &tr)
{
	SeekToBegin();
	igp_construct_pxp_tree(this, 0, &tr, m_info.platform);
	return 1;
}

int IgorProFile::GetAxis(vector &vd, int dim)
{
	vd.SetSize(m_info.nDim[dim]);
	vd.Data(m_info.sfB[dim], m_info.sfA[dim]*(m_info.nDim[dim]-1), m_info.sfA[dim]);
	return 1;
}

// Read variables
int IgorProFile::ImportVariables(Worksheet &wks, TreeNode &tr)
{
	// Fisher: Not handle this at this time
	if ( wks && tr.GetNodeCount()>0 ){
		impinfo_AddFile(wks, m_strFileName, tr, ASCIMP_MODE_NEW_SHEETS, FILTER_TYPE_XFUNC);
	}
	
	return 1;
}

int IgorProFile::ImportWave(string strName, Worksheet &wks)
{
	switch (m_info.dim) {
	case IGP_WAVE_DIM1:
		if ( !wks ){
			WorksheetPage wp;
			wp.Create("Origin");
			wks = wp.Layers(0);
			m_nColIndex = 1;
		}
		if(wks.GetNumCols()<m_nColIndex)
			wks.SetSize(-1, m_nColIndex);
			
		Column col(wks,m_nColIndex-1);
		col.SetName(strName);
		col.SetLongName(strName);
		col.SetType(OKDATAOBJ_DESIGNATION_Y );
		
		// Set sampling interval
		if( fabs(m_info.sfA[0]) >= 0.000001 )
			col.SetEvenSampling(m_info.sfB[0], m_info.sfA[0]);
		
		string strRange;
		strRange.Format("%s!%d",wks.m_strBookSheet, m_nColIndex++);
		if(m_info.type != FSI_MIXED)
			return igp_read_data(strRange, this, m_nBaseOffset, &m_info, 0, 0, 0, 1);
		break;

	case IGP_WAVE_DIM2:
	case IGP_WAVE_DIM3:
	case IGP_WAVE_DIM4:
		// X, Y, Z and T axis

		//Import to matrix
		int ii, jj, d2, d3;
		d2 = m_info.nDim[2]?m_info.nDim[2]:1;
		d3 = m_info.nDim[3]?m_info.nDim[3]:1;
		
        MatrixPage mp;
        MatrixObject mo;
		mp.Create("origin");
		
		mp.Label = strName;
		mp.TitleShow = WIN_TITLE_SHOW_BOTH;
		
		for(ii=0; ii<d3-1; ++ii)
			mp.AddLayer();
		for(ii=0; ii<d3; ++ii){
			MatrixLayer ml = mp.Layers(ii);
			if(d2>1)
				ml.Insert(d2-1);
			for(jj=0; jj<d2; ++jj){
				Import2Matrix(ml, jj, jj, ii);
			}
			// Transpose the matrix for numeric wave
			if(m_info.nDim[1]<30){
				bool	bTransposed = false;
				foreach(mo in ml.MatrixObjects){
					matrixbase& mat = mo.GetDataObject();
					if( !bTransposed ){
						bTransposed = true;
						mat.Transpose();
					}
				}
			}
			
			//Set page name
			string strTmp;
			if(1 == d3 && 1 == d2)
				strTmp.Format("%s", strName);
			else if(1 == d3 && 1 != d2)
				strTmp.Format("%s___", strName);
			else if(1 != d3 && 1 != d2)
				strTmp.Format("%s____%d", strName, ii);
			else
				ASSERT(false);	
			
			ml.SetName(strTmp);
			
		}
		// Set as image mode
		if(m_info.nDim[1]>=30)
			mp.SetViewMode(TRUE, TRUE);

		break;
	default:
		return -1;
		break;
	}

	return -1;

}

int IgorProFile::ImportALL(TreeNode &tr, string path, Worksheet& wks)
{
	string strLabel;
	int nType, nDataOffset;
	Tree trVar;

	foreach(TreeNode cNode in tr.Children)
	{
		Project.ActivateFolder(path);
		if(cNode.GetNodeCount() > 0)
		{
			// Support selection on folder			
			int val;
			cNode.GetAttribute(STR_STOP_ATTRIB, val);
			if(0 == val) continue;
			
			if(!cNode.GetAttribute(STR_LABEL_ATTRIB, strLabel))
				strLabel = tr.tagName;
			Folder fld = Project.ActiveFolder();
			fld.AddSubfolder(strLabel);
			string strNext = path+strLabel+"/";	
			Project.ActivateFolder(strNext);

			Worksheet wksNext;
			ImportALL(cNode, strNext, wksNext);
		}
		else
		{
			// Support selection on item
			if(0 == cNode.nVal)	continue;
			
			if(!cNode.GetAttribute(STR_LABEL_ATTRIB, strLabel))
				strLabel = tr.tagName;
			cNode.GetAttribute(STR_DATAID_ATTRIB, nType);
			cNode.GetAttribute(STR_DATA_ATTRIB, nDataOffset);

			// TODO Import Type
			m_nBaseOffset = nDataOffset;	
			switch(nType){
				case kWaveRecord:
					igp_read_header(this, m_nBaseOffset, &m_info, 1);
					ImportWave(strLabel, wks);
					break;
				case kVariablesRecord:
					igp_get_variables(this, m_nBaseOffset, &trVar);
					break;
				case kDataFolderStartRecord:
					Folder fld = Project.ActiveFolder();
					fld.AddSubfolder(strLabel);
					break;					
				default:
					break;
			}
			// TODO

		}

	}

	Project.ActivateFolder(path);
	ImportVariables(wks, trVar);
	
	return 1;
}


// Interface for import bin file
int IgorProFile::ImportIBW(Worksheet& wks, int nCol)
{
	if (!IsOpen()) {
		printf("Fail to load file : %s\n", m_strFileName);
		return IMPERR_FILE_OPEN;
	}

	igp_read_header(this, 0, &m_info, 0);
	m_nBaseOffset = 0;
	m_nColIndex = nCol+1;
	return ImportWave(m_info.bname, wks);
}


