// TableRow.cpp: implementation of the CTableRow class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "resource.h"
#include "ReportDict.h"
#include <ctype.h>
#include "Functions.h"
#include "CommonQuery.h"
#include <aplxml.h>

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
//======================================================================
CaplReportValue::CaplReportValue()
{
	m_text_color = m_line_color = ::GetSysColor(COLOR_WINDOWTEXT);
	m_background_color = ::GetSysColor(COLOR_WINDOW);
	
	m_bStrikeOut = FALSE;

	m_bold = FALSE;
	m_italic = FALSE;
}

CaplReportValue::~CaplReportValue()
{
}
//===========================Строка таблицы=============================
CTableRow::CTableRow(bool bCorrectQuotes /*= false*/) : m_bCorrectQuotes(bCorrectQuotes)
{
	m_Data.RemoveAll();
}

CTableRow::~CTableRow()
{
	RemoveAll();
}

int CTableRow::AddColumn(CaplReportValue *val)
{
	return m_Data.Add(val);
}

int CTableRow::AddColumn(CString val, COLORREF text_color)
{
	CaplReportValue* cval = new CaplReportValue;
	cval->Set(m_bCorrectQuotes?CorrectQuotes(val):val);
	cval->m_text_color = text_color;
	return m_Data.Add(cval);
}

int CTableRow::AddColumn(double val)
{
	CaplReportValue* cval = new CaplReportValue;
	cval->Set(val);
	return m_Data.Add(cval);
}

int CTableRow::AddColumn(int val)
{
	CaplReportValue* cval = new CaplReportValue;
	cval->Set(val);
	return m_Data.Add(cval);
}

int CTableRow::AddColumn(CaplInstance* val)
{
	CaplReportValue* cval = new CaplReportValue;
	cval->Set(val);
	return m_Data.Add(cval);
}

int CTableRow::AddColumn(CaplAggr& val)
{
	CaplReportValue* cval = new CaplReportValue;
	cval->Set(val);
	return m_Data.Add(cval);
}

CaplReportValue* CTableRow::GetColumn(int pos)
{
	if(pos<0 || pos>=m_Data.GetSize()) return NULL;
	return m_Data.GetAt(pos);
}

CString CTableRow::GetAsString(int pos)
{
	if(pos<0 || pos>=m_Data.GetSize()) return _T("");
	CaplReportValue* val = m_Data.GetAt(pos);
	return ::GetAsString(val);
}

int CTableRow::GetColumnType(int pos)
{
	if(pos<0 || pos>=m_Data.GetSize()) return NULL;
	return m_Data.GetAt(pos)->type;
}

int CTableRow::GetSize()
{
	return m_Data.GetSize();
}

int CTableRow::Find(CaplReportValue* val)
{
	int cnt = m_Data.GetSize();
	for(int i=0;i<cnt;i++)
		if(m_Data.GetAt(i)==val) return i;
	return -1;
}

void CTableRow::GetAsCSVRow(CString &sRow, char pSep)
{
	sRow = _T("");
	int cnt = m_Data.GetSize();
	CString sTmp;
	for(int i=0; i<cnt;i++)
	{
		sTmp = GetAsString(i);
		m_Data.GetAt(i);
		if(i>0)
		{
			sRow+=pSep;
			sRow+=_T("\"")+sTmp+_T("\"");
		}
		else
			sRow+=_T("\"")+sTmp+_T("\"");
	}
}

void CTableRow::RemoveAt(int pos)
{
	if(pos<0 || pos>=m_Data.GetSize()) return;
	CaplReportValue* val = m_Data.GetAt(pos);
	delete val;
	m_Data.RemoveAt(pos);
}

void CTableRow::RemoveAll()
{
	int i, cnt = m_Data.GetSize();
	for(i=0; i<cnt; i++)
	{
		CaplReportValue* val = m_Data.GetAt(i);
		delete val;
	}
	m_Data.RemoveAll();
}

int CTableRow::InsertColumn(int pos, CaplReportValue *col)
{
	if(pos==-1) return AddColumn(col);
	m_Data.InsertAt(pos,col);
	return pos;
}

bool CTableRow::SetAt(int i, CaplReportValue* val)
{
	if(i<0 || i>=m_Data.GetSize()) return false;
	m_Data.SetAt(i,val);
	return true;
}

bool CTableRow::SetAt(int i, CString sVal)
{
	if(i<0 || i>=m_Data.GetSize()) return false;
	CaplReportValue *pVal = m_Data.GetAt(i);
	pVal->Set(sVal);
	return true;
}
//===========================Строка таблицы - end=============================
CHeaderColumn& CHeaderColumn::operator =(const CHeaderColumn &header)
{
	m_name = header.m_name;
	m_inst = NULL;
	m_type = header.m_type;
	m_col_type = header.m_col_type;
	m_sFormat =  header.m_sFormat;
	return *this;
}

//===========================Header===========================================
CHeader::CHeader(CaplReportMgr *reportmgr, bool bBaseSource)
{
	m_ReportMgr = reportmgr;
	m_inst = NULL;
	m_Data.RemoveAll();

	m_bBaseSource = bBaseSource;
}

CHeader::~CHeader()
{
	RemoveAll();
}
void CHeader::Update(bool set)
{
	if(m_ReportMgr==NULL) return;
	if(set)
	{
		int cnt = m_Data.GetSize();
		aplExtent ext;
		int i;
		CHeaderColumn* val;

		if(m_inst==NULL)
			m_inst = m_ReportMgr->m_data->CreateInstance(m_bBaseSource ? m_ReportMgr->e_apl_select:m_ReportMgr->e_apl_result_select);
		for(i=0; i<cnt;i++)
		{
			val = m_Data.GetAt(i);
			val->Update(set);
			ext.Add(val->m_inst);
		}
		m_ReportMgr->m_data->PutAttr(m_inst, m_bBaseSource?m_ReportMgr->a_apl_sel_cols:m_ReportMgr->a_apl_res_sel_cols, ext);
	}
	else
	{
		RemoveAll();
		if(m_inst==NULL) return;

		CHeaderColumn* val;
		aplExtent ext;
		int cnt, i;

		m_bBaseSource = m_ReportMgr->m_data->IsKindOf(m_inst, m_ReportMgr->e_apl_select);
		m_ReportMgr->m_data->GetAttr(m_inst, m_bBaseSource?m_ReportMgr->a_apl_sel_cols:m_ReportMgr->a_apl_res_sel_cols, ext);
		cnt = ext.GetSize();

		for(i=0; i<cnt;i++)
		{
			if(ext[i]==NULL) continue;

			val = new CHeaderColumn(m_ReportMgr);
			val->m_inst = ext[i];
			val->Update(set);
			m_Data.Add(val);
		}
	}
}

int CHeader::AddColumn(CHeaderColumn* val)
{
	return m_Data.Add(val);
}

int CHeader::AddColumn(CString name, int type)
{
	CHeaderColumn* val = new CHeaderColumn(m_ReportMgr);
	val->m_name = name;
	val->m_type = type;
	return m_Data.Add(val);
}

CHeaderColumn* CHeader::GetColumn(int pos)
{
	if(pos<0 || pos>=m_Data.GetSize()) return NULL;
	return m_Data.GetAt(pos);
}

int CHeader::GetColumnType(int pos)
{
	if(pos<0 || pos>=m_Data.GetSize()) return NULL;
	return m_Data.GetAt(pos)->m_type;
}

int CHeader::GetSize()
{
	return m_Data.GetSize();
}

int CHeader::Find(CHeaderColumn* val)
{
	int cnt = m_Data.GetSize();
	for(int i=0; i<cnt;i++)
		if(m_Data.GetAt(i)==val) return i;
	return -1;
}

int CHeader::Find(CString name)
{
	int cnt = m_Data.GetSize();
	for(int i=0; i<cnt;i++)
		if(m_Data.GetAt(i)->GetName().CompareNoCase(name)==0) return i;
	return -1;
}

void CHeader::RemoveAt(int pos)
{
	if(pos<0 || pos>=m_Data.GetSize()) return;
	CHeaderColumn* val = m_Data.GetAt(pos);
	DELETE_OBJECT(val);
	m_Data.RemoveAt(pos);
}

void CHeader::RemoveAll()
{
	int cnt = m_Data.GetSize();
	for(int i=0; i<cnt;i++)
	{
		CHeaderColumn* val = m_Data.GetAt(i);
		DELETE_OBJECT(val);
	}
	m_Data.RemoveAll();
}

void CHeader::GetAsCSVRow(CString &sRow, char pSep)
{
	sRow = _T("");
	int cnt = m_Data.GetSize();
	for(int i=0; i<cnt;i++)
	{
		CHeaderColumn* val = m_Data.GetAt(i);
		if(i>0)
		{
			sRow+=pSep;
			sRow+=_T("\"")+val->GetName()+_T("\"");
		}
		else
			sRow+=_T("\"")+val->GetName()+_T("\"");
	}
}

int CHeader::InsertColumn(int pos, CHeaderColumn *col)
{
	if(pos==-1) return AddColumn(col);
	m_Data.InsertAt(pos,col);
	return pos;
}

//===========================Header - end=====================================//

int CHeader::Find(CaplInstance *inst)
{
	int cnt = m_Data.GetSize();
	for(int i=0; i<cnt;i++)
		if(m_Data.GetAt(i)->m_inst==inst) return i;
	return -1;
}

void CHeader::Delete()
{
	if(m_ReportMgr==NULL) return;
	if(m_inst==NULL) return;

	int cnt = m_Data.GetSize();
	for(int i=0; i<cnt;i++)
		if(m_Data.GetAt(i)->m_inst!=NULL)
			m_ReportMgr->m_data->DeleteInstance(m_Data.GetAt(i)->m_inst);
	m_ReportMgr->m_data->DeleteInstance(m_inst);

	RemoveAll();
}

void CHeader::Clear()
{
	m_Data.RemoveAll();
}


bool CParamArray::SaveToBuf(CString &buf)
{
	int i, cnt;
	CString tmp, name, val;
	if(buf.IsEmpty())
		buf=_T("Data Source File\n");
	buf+=_T("[Params]\n");
	cnt = m_Data.GetSize();
	for(i=0; i<cnt; i++)
	{
		name = m_Data[i]->m_name;
		val = m_Data[i]->GetText();
		val.Replace(_T("\\n"), _T("\\\\n"));
		val.Replace(_T("\n"), _T("\\n"));
		val.Replace(_T("\r"), _T(""));
		tmp = name+_T("=")+val+_T("\n");
		buf+=tmp;
	}
	return true;
}

void CHeaderColumn::Delete()
{
	if(m_inst && m_ReportMgr)
		m_ReportMgr->m_data->DeleteInstance(m_inst);
}

CString CHeaderColumn::GetName()
{
	if(m_col_type!=APL_COMBINE_COLUMN) return m_name;
	int ind = m_name.Find(_T("="));
	if(ind<0) return m_name;
	return m_name.Left(ind);
}

CString CHeaderColumn::GetFunct()
{
	if(m_col_type!=APL_COMBINE_COLUMN) return _T("");
	int ind = m_name.Find(_T("="));
	if(ind<0) return _T("");
	return m_name.Right(m_name.GetLength()-ind-1);
}

CString CHeaderColumn::GetType()
{
	CString str = _T("aplNOTYPE");
	if(m_type==aplREAL)
		str=_T("aplREAL");
	else if(m_type==aplINTEGER)
		str=_T("aplINTEGER");
	else if(m_type==aplSTRING)
		str=_T("aplSTRING");
	else if(m_type==aplBINARY)
		str=_T("aplBINARY");
	else if(m_type==aplINSTANCE)
		str=_T("aplINSTANCE");
	return str;
}

void CHeaderColumn::Update(bool bStoring)
{
	if(!m_ReportMgr) return;
	
	if(bStoring)
	{
		if(m_inst==NULL)
			m_inst = m_ReportMgr->m_data->CreateInstance(m_ReportMgr->e_apl_data_src_col);
		m_ReportMgr->m_data->PutAttr(m_inst, m_ReportMgr->a_apl_col_type, m_type);
		m_ReportMgr->m_data->PutAttr(m_inst, m_ReportMgr->a_apl_col_name, m_name);
		m_ReportMgr->m_data->PutAttr(m_inst, m_ReportMgr->a_apl_col_type_col, m_col_type);
	}
	else
	{
		if(m_inst==NULL) return;

		m_ReportMgr->m_data->GetAttr(m_inst, m_ReportMgr->a_apl_col_type, m_type);
		m_ReportMgr->m_data->GetAttr(m_inst, m_ReportMgr->a_apl_col_name, m_name);
		m_ReportMgr->m_data->GetAttr(m_inst, m_ReportMgr->a_apl_col_type_col, m_col_type);
	}
}

CString CTableRow::CorrectQuotes(const CString& sValue)
{
	CString sResult;
	if (sValue.IsEmpty())
		return sResult;

	sResult = sValue;

	int iCount(0), iStart(-1);
	while(-1<(iStart=sResult.Find(_T("\""), ++iStart)))
		++iCount;

	if (iCount%2>0)
		sResult.Replace(_T("\""), _T("''"));

	return sResult;
}