// XmlIcon.cpp: implementation of the CXmlIcon class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ascfgbuilder.h"
#include "XmlIcon.h"
#include <vector>
#include "FileUtils.h"
#include "MainFrm.h"
#include "CPathSplit.h"

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

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CXmlIcon::CXmlIcon():
	hIcon16_(NULL),
	hIcon32_(NULL)
{

}

CXmlIcon::CXmlIcon(const CXmlIcon& c)
{
	Copy(c);
}

CXmlIcon::~CXmlIcon()
{
	ReleaseIconHandle();
}

bool CXmlIcon::BuildFromXml(IXMLDOMNode* node)
{
	// if loading an old version each "Icon" node has a text part
	// containing the full name of the icon
	//
	cmString fullFileName;

	ExtractTextNode(node, fullFileName);
	if (fullFileName == _T("")) {
		ExtractMemberNode(node, _T("FileName"), fileName_);
		ExtractCDATAMemberNode(node, fileContent_);

		fullFileName = CMainFrame::GetTmpPath();
		fullFileName += _T("\\");
		fullFileName += fileName_;
		
		WriteToFile(fullFileName);
		LoadFile(fullFileName);
		::DeleteFile(fullFileName);

	} else {
		LoadFile(fullFileName);
	}
	
	return true;
}

bool CXmlIcon::AppendToDOMDocument(IXMLDOMDocument2* xmlDoc, IXMLDOMElement* parentElement)
{
	CComPtr<IXMLDOMElement> newElement;
	HRESULT hr;

	hr = xmlDoc->createElement(CComBSTR((const TCHAR*)GetXmlNodeName()), &newElement);

	AppendMemberNode(_T("FileName"), fileName_, newElement, xmlDoc);
	AppendCDATAMemberNode(fileContent_, newElement, xmlDoc);

	if (parentElement)
		hr = parentElement->appendChild(newElement, NULL);
	else
		hr = xmlDoc->appendChild(newElement, NULL);

	return true;
}

CXmlIcon& CXmlIcon::operator=(const CXmlIcon& c)
{
	Copy(c);

	return *this;
}

void CXmlIcon::Copy(const CXmlIcon& c)
{
	fileName_ = c.GetFileName();
	hIcon16_ = c.GetIconHandle16();
	hIcon32_ = c.GetIconHandle32();
}

void CXmlIcon::Clear()
{}

void CXmlIcon::SetDefaults()
{}

void CXmlIcon::SetFileName(const cmString& fileName)
{
	fileName_ = fileName;
}

cmString CXmlIcon::GetFileName() const
{
	return fileName_;
}


HICON CXmlIcon::GetIconHandle16() const
{
	return hIcon16_;
}

HICON CXmlIcon::GetIconHandle32() const
{
	return hIcon32_;
}

void CXmlIcon::SetKey(const cmString& key)
{
	key_ = key;
}

cmString CXmlIcon::GetKey() const
{
	return key_;
}

bool CXmlIcon::LoadFile(const cmString& fileName)
{
	// load the icon into a HICON object
	//
	if (!CreateIconHandle(fileName))
		return false;
	
	// 2) creates a cdata object for further serialization
	//
	vector<BYTE> binaryContent;
	cmString tmp;
	TCHAR* buf;
	int bufSize;

	if (!CFileUtils::ReadBinaryFile(fileName, binaryContent))
		return false;
	
	bufSize = binaryContent.size() * 2 + 1;
	buf = new TCHAR[bufSize];
	memset(buf, 0, bufSize);
	fileContent_ = _T("");

	for (int i = 0; i < binaryContent.size(); i++) {
		tmp.Format(_T("%02X"), binaryContent[i]);
#ifdef UNICODE
		wcscat(buf, (const TCHAR*)tmp);
#else
		strcat(buf, (const TCHAR*)tmp);
#endif
		//fileContent_ += tmp;
	}

	fileContent_ = buf;
	delete [] buf;

	CPathSplit p(fileName);

	fileName_ = p.GetFileName() + p.GetExtension();

	return true;
}

void CXmlIcon::ReleaseIconHandle()
{
	if (hIcon16_) {
		::DestroyIcon(hIcon16_);
		hIcon16_ = NULL;
	}

	if (hIcon32_) {
		::DestroyIcon(hIcon32_);
		hIcon32_ = NULL;
	}
}

bool CXmlIcon::WriteToFile(const cmString& fileName)
{
	vector<BYTE> buf;
	cmString tmp;
	BYTE value;
	bool ret;

	//buf.reserve(fileContent_.GetLength() / 2);
	for (int i = 0; i < fileContent_.GetLength(); i+=2) {
		
		tmp=fileContent_.Mid(i, 2);
		
#ifdef UNICODE
		swscanf((const TCHAR*)tmp, _T("%02X"), &value);	
#else
		sscanf((const TCHAR*)tmp, _T("%02X"), &value);	
#endif
		buf.push_back(value);
	}

	ret = CFileUtils::WriteBinaryFile(fileName, buf);

	return ret;
}

bool CXmlIcon::CreateIconHandle(const cmString& fileName)
{
	ReleaseIconHandle();
	
	hIcon16_ = (HICON)::LoadImage(AfxGetInstanceHandle(), fileName, IMAGE_ICON, 16, 16, LR_LOADFROMFILE | LR_SHARED/* | LR_LOADTRANSPARENT*/);
	hIcon32_ = (HICON)::LoadImage(AfxGetInstanceHandle(), fileName, IMAGE_ICON, 32, 32, LR_LOADFROMFILE | LR_SHARED/* | LR_LOADTRANSPARENT*/);

	return (hIcon16_ != NULL && hIcon32_ != NULL);
} 