#include "stdafx.h"
#include "ExcelWorksheetRef.h"	// CExcelWorksheetRef
#include <float.h>							// FLT_MAX


CExcelWorksheetRef::CExcelWorksheetRef() :m_nodeTableWorksheet(0), m_dwCurrentLine(0), 
	m_dwLastDestX(0), m_dwLastDestY(0)
{
}

void CExcelWorksheetRef::SetRef( TiXmlNode *nodeTableWorksheet )
{
	m_nodeTableWorksheet=nodeTableWorksheet;
}

uint32 CExcelWorksheetRef::FindColumn( const char *szColumnName, const uint32 dwDefault )
{
	TiXmlNode *nodeRow=m_nodeTableWorksheet->FirstChild("Row");

	if(!nodeRow)
		return dwDefault;

	uint32 dwRet=0;

	for(TiXmlNode *nodeCell=nodeRow->FirstChild("Cell");nodeCell; nodeCell=nodeCell->NextSibling(),++dwRet)
	{
		TiXmlNode *nodeData = nodeCell->FirstChild("Data");

		if(!nodeData)
			continue;		// data not found

		TiXmlNode *nodeValue = nodeData->FirstChild();

		if(!nodeValue)
			continue;

		if(stricmp(szColumnName,nodeValue->Value())==0)
			return dwRet;
	}

	return dwDefault;
}


TiXmlNode *CExcelWorksheetRef::FindTableCell( const uint32 dwX, const uint32 dwY )
{
	assert(m_nodeTableWorksheet);		if(!m_nodeTableWorksheet)return 0;

	uint32 dwCurrY=0;
	TiXmlNode *nodeRow = m_nodeTableWorksheet->FirstChild("Row");
	
	for(;;nodeRow=nodeRow->NextSibling(),++dwCurrY)
	{
		if(!nodeRow)
		{
			TiXmlElement elRow("Row");
			nodeRow = m_nodeTableWorksheet->InsertEndChild(elRow);
		}

		if(dwCurrY==dwY)
		{
			uint32 dwCurrX=0;
			TiXmlNode *nodeCell=nodeRow->FirstChild("Cell");

			for(;;nodeCell=nodeCell->NextSibling(),++dwCurrX)
			{
				if(!nodeCell)
				{
					TiXmlElement elCell("Cell");
					nodeCell = nodeRow->InsertEndChild(elCell);
				}

				if(dwCurrX==dwX)
					return nodeCell;
			}
			return 0;
		}
	}

	return 0;
}


void CExcelWorksheetRef::SetColumWidth( const uint32 dwX, const float fExtend )
{
	if(!m_nodeTableWorksheet)
		return;

	uint32 dwCurrX=0;
	for(TiXmlNode *nodeCol=m_nodeTableWorksheet->FirstChild("Column");; nodeCol=nodeCol->NextSibling(),++dwCurrX)
	{
		if(!nodeCol)
		{
			TiXmlElement elRow("Column");
			nodeCol = m_nodeTableWorksheet->InsertEndChild(elRow);
		}

		if(dwCurrX==dwX)
		{
			TiXmlElement *pEl = nodeCol->ToElement();			assert(pEl);

			pEl->SetAttribute("ss:AutoFitWidth","0");
			pEl->SetAttribute("ss:Width",(int)fExtend);
			return;
		}
	}

	assert(0);		// internal error
}


void CExcelWorksheetRef::SetStringValueAt( const uint32 dwX, const uint32 dwY, const char *szString,
	const char *szStyleID )
{
	TiXmlNode *nodeCell = FindTableCell(dwX,dwY);				assert(nodeCell);
	TiXmlNode *nodeData = nodeCell->FirstChild("Data");

	if(!nodeData)
	{
		TiXmlElement elData("Data");
		elData.SetAttribute("ss:Type","String");

		nodeData = nodeCell->InsertEndChild(elData);
	}

	if(szStyleID)
		nodeCell->ToElement()->SetAttribute("ss:StyleID",szStyleID);

	TiXmlText elText(szString);

	nodeData->Clear();		// don't add data - overwrite existing value
	nodeData->InsertEndChild(elText);
}


void CExcelWorksheetRef::SetValueAt( const uint32 dwX, const uint32 dwY, const float fValue, 
	const char *szStyleID )
{
	TiXmlNode *nodeCell = FindTableCell(dwX,dwY);				assert(nodeCell);
	TiXmlNode *nodeData = nodeCell->FirstChild("Data");

	if(!nodeData)
	{
		TiXmlElement elData("Data");
		elData.SetAttribute("ss:Type","Number");
		nodeData = nodeCell->InsertEndChild(elData);
	}
	else assert(0);			// ?

	char str[80];

	sprintf_s(str,sizeof(str),"%f",fValue);

	if(szStyleID)
		nodeCell->ToElement()->SetAttribute("ss:StyleID",szStyleID);

	TiXmlText elText(str);

	nodeData->Clear();		// don't add data - overwrite existing value
	nodeData->InsertEndChild(elText);
}

/*
void CExcelWorksheetRef::InsertColumn( const uint32 dwX )
{
	TiXmlNode *node = FindTableCell(dwX,0);			assert(node);
	TiXmlNode *parent = node->Parent();					assert(parent);
	
	TiXmlElement elRow("Row");

	parent->InsertAfterChild(node,elRow);
}
*/

uint32 CExcelWorksheetRef::GetWidth()
{
	return m_dwLastDestX;
}

void CExcelWorksheetRef::ExtendByOneLine()
{
	++m_dwLastDestY;
}

uint32 CExcelWorksheetRef::GetHeight()
{
	return m_dwLastDestY;
}
/*
void CExcelWorksheetRef::ReadLineAssignments()
{
	assert(m_nodeTableWorksheet);

//	m_LineAssignment.clear();
//	m_dwCurrentLine=0;

	ComputeExtend();

	for(uint32 dwLine=0;dwLine<m_dwLastDestY;++dwLine)
	{
		std::string sVal = GetValueAt(0,dwLine);

		if(!sVal.empty())
		{
//			assert(m_LineAssignment.find(sVal)==m_LineAssignment.end());
			m_LineAssignment[sVal]=dwLine;
		}
	}

}
*/


void CExcelWorksheetRef::ComputeExtend()
{
	assert(m_nodeTableWorksheet);

	m_dwLastDestX=0;m_dwLastDestY=0;

	for(TiXmlNode *nodeRow=m_nodeTableWorksheet->FirstChild("Row");nodeRow; nodeRow=nodeRow->NextSibling())
	{
		uint32 dwCurrX=0;
		for(TiXmlNode *nodeCell=nodeRow->FirstChild("Cell");nodeCell; nodeCell=nodeCell->NextSibling(),++dwCurrX)
		{
			if(dwCurrX>m_dwLastDestX)
				m_dwLastDestX=dwCurrX;
		}

		++m_dwLastDestY;
	}

	++m_dwLastDestX;
}




uint32 CExcelWorksheetRef::FindLineBasedOnKey( const std::string sLevelKey, const std::string sEntryKey, const char *szStyleID )
{
	if(sEntryKey.empty())
		return 0xffffffff;				// not valid

	std::string sKey = sEntryKey;

	if(!sLevelKey.empty())
		sKey = sLevelKey + "~" + sEntryKey;

	std::map<std::string,uint32>::const_iterator it = m_LineAssignment.find(sKey);

	if(it==m_LineAssignment.end())
	{
		uint32 dwLine = m_dwLastDestY++;
		m_LineAssignment[sKey] = dwLine;

		if(!szStyleID)
			szStyleID="s21";			// s21:bold+left aligned, s25:green background+bold,
		
		uint32 dwCol=0;

		if(!sLevelKey.empty())
			SetStringValueAt(dwCol++,dwLine,sLevelKey.c_str(),szStyleID);

		SetStringValueAt(dwCol,dwLine,sEntryKey.c_str(),szStyleID);

		return dwLine;
	}
	else 
		return it->second;
}

std::string CExcelWorksheetRef::GetValueAt( const uint32 dwX, const uint32 dwY )
{
	TiXmlNode *nodeCell = FindTableCell(dwX,dwY);				assert(nodeCell);

	std::string sRet;

	if(!nodeCell)
		return sRet;		// cell not found

	TiXmlNode *nodeData = nodeCell->FirstChild("Data");

	if(!nodeData)
		return sRet;		// data not found

	TiXmlNode *nodeValue = nodeData->FirstChild();

	if(!nodeValue)
		return sRet;		// 

	sRet = nodeValue->Value();

	return sRet;
}		



