/*
	BinMaker program
	Copyright 2007 Jonathan Wilson
	Portions lifted from BinOpener copyright 2007 booto (temptemp91 at hotmail dot com)

	This file is part of binmaker.

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.

	binmaker is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

*/
#include <stdio.h>
#include "tinyxml.h"
#include "manifestitem.h"
#include "missionobjectivelist.h"
MissionObjectiveList::MissionObjectiveList(TiXmlNode *node)
{
	const char *id = node->ToElement()->Attribute("id");
	char *stream = new char[strlen(id)+22];
	StreamSize = sizeof(MissionObjectiveListHeader);
	offset = 0;
	currentimport = 0;
	std::vector<Objective *> objectives;
	sprintf(stream,"MissionObjectiveList:%s",id);
	StreamName = stream;
	SourceName = _strdup("DATA:map.xml");
	_strlwr((char *)id);
	Header.filenamehash1 = 0x6cddc801;
	Header.filenamehash2 = hash_function(id,strlen(id));
	Header.filenamehash3 = 0xc385a8c1;
	Header.filenamehash4 = Header.filenamehash2;
	for (TiXmlNode *child = node->FirstChild(); child; child = child->NextSibling())
	{
		if (child->Type() != TiXmlNode::ELEMENT)
		{
			continue;
		}
		if (child->ValueStr() == "MissionObjective")
		{
			Objective *o = new Objective;
			objectives.push_back(o);
			StreamSize += sizeof(MissionObjective);
			o->name = child->ToElement()->Attribute("Name");
			int len = strlen(o->name);
			StreamSize += (len + (4 - (len % 4)));
			o->detail = child->ToElement()->Attribute("Detail");
			len = strlen(o->detail);
			StreamSize += (len + (4 - (len % 4)));
			const char *b = child->ToElement()->Attribute("Bonus");
			if (!_stricmp(b,"false"))
			{
				o->bonus = false;
			}
			else
			{
				o->bonus = true;
			}
			for (TiXmlNode *child2 = child->FirstChild(); child2; child2 = child2->NextSibling())
			{
				if (child2->Type() != TiXmlNode::ELEMENT)
				{
					continue;
				}
				if (child2->ValueStr() == "PresentationSettings")
				{
					ObjectivePresentation *p = new ObjectivePresentation;
					o->obj.push_back(p);
					StreamSize += sizeof(MissionObjectivePresentation);
					p->name = child2->ToElement()->Attribute("Name");
					int len = strlen(p->name);
					StreamSize += (len + (4 - (len % 4)));
					const char *obj = child2->ToElement()->Attribute("SoundFile");
					if (obj[0])
					{
						_strlwr((char *)obj);
						p->import.filehash1 = 0x844d7b9f;
						p->import.filehash2 = hash_function(obj,strlen(obj));
					}
					else
					{
						p->import.filehash1 = 0;
						p->import.filehash2 = 0;
					}
					child2->ToElement()->Attribute("psa",&(p->a));
					if (p->a)
					{
						StreamSize += 4;
					}
					child2->ToElement()->Attribute("psb",&(p->b));
					if (p->b)
					{
						StreamSize += 4;
					}
					child2->ToElement()->Attribute("psc",&(p->c));
					if (p->c)
					{
						StreamSize += 4;
					}
					child2->ToElement()->Attribute("psd",&(p->d));
					if (p->d)
					{
						StreamSize += 4;
					}
					child2->ToElement()->Attribute("pse",&(p->e));
					if (p->e)
					{
						StreamSize += 4;
					}
					const char *b = child2->ToElement()->Attribute("psunk");
					if (!_stricmp(b,"false"))
					{
						p->unknown = false;
					}
					else
					{
						p->unknown = true;
					}
				}
			}
		}
	}
	StreamData = new char[StreamSize];
	memset(StreamData,0,StreamSize);
	MissionObjectiveListHeader *mh = (MissionObjectiveListHeader *)(StreamData+offset);
	offset += sizeof(MissionObjectiveListHeader);
	mh->zeroes = 0;
	mh->scripts.length = objectives.size();
	mh->scripts.offset = offset;
	RelocationEntries.push_back((char *)(&(mh->scripts.offset)) - StreamData);
	offset += (sizeof(MissionObjective) * objectives.size());
	MissionObjective *mo = (MissionObjective *)(StreamData+mh->scripts.offset);
	for (unsigned int i = 0;i < objectives.size();i++)
	{
		mo[i].name.length = strlen(objectives[i]->name);
		mo[i].name.offset = offset;
		RelocationEntries.push_back((char *)(&(mo[i].name.offset)) - StreamData);
		strcpy((char *)(StreamData+offset),objectives[i]->name);
		int len = strlen(objectives[i]->name);
		offset += (len + (4 - (len % 4)));
		mo[i].detail.length = strlen(objectives[i]->detail);
		mo[i].detail.offset = offset;
		RelocationEntries.push_back((char *)(&(mo[i].detail.offset)) - StreamData);
		strcpy((char *)(StreamData+offset),objectives[i]->detail);
		len = strlen(objectives[i]->detail);
		offset += (len + (4 - (len % 4)));
		mo[i].obj.length = objectives[i]->obj.size();
		mo[i].obj.offset = offset;
		RelocationEntries.push_back((char *)(&(mo[i].obj.offset)) - StreamData);
		MissionObjectivePresentation *mop = (MissionObjectivePresentation *)(StreamData+offset);
		offset += sizeof(MissionObjectivePresentation) * objectives[i]->obj.size();
		for (unsigned int j = 0;j < objectives[i]->obj.size();j++)
		{
			mop[j].name.length = strlen(objectives[i]->obj[j]->name);
			mop[j].name.offset = offset;
			RelocationEntries.push_back((char *)(&(mop[j].name.offset)) - StreamData);
			strcpy((char *)(StreamData+offset),objectives[i]->obj[j]->name);
			int len = strlen(objectives[i]->obj[j]->name);
			offset += (len + (4 - (len % 4)));
			if (objectives[i]->obj[j]->import.filehash1)
			{
				mop[j].import = currentimport;
				currentimport++;
				unsigned int imp = ((char *)(&(mop[j].import)) - StreamData);
				unsigned int hash1 = objectives[i]->obj[j]->import.filehash1;
				unsigned int hash2 = objectives[i]->obj[j]->import.filehash2;
				AddImport(hash1,hash2,imp);
			}
			else
			{
				mop[j].import = 0;
			}
			if (objectives[i]->obj[j]->a)
			{
				mop[j].a.offset = offset;
				RelocationEntries.push_back((char *)(&(mop[j].a.offset)) - StreamData);
				(*((float *)(StreamData+offset))) = objectives[i]->obj[j]->a;
				offset += 4;
			}
			else
			{
				mop[j].a.offset = 0;
			}
			if (objectives[i]->obj[j]->b)
			{
				mop[j].b.offset = offset;
				RelocationEntries.push_back((char *)(&(mop[j].b.offset)) - StreamData);
				(*((float *)(StreamData+offset))) = objectives[i]->obj[j]->b;
				offset += 4;
			}
			else
			{
				mop[j].b.offset = 0;
			}
			if (objectives[i]->obj[j]->c)
			{
				mop[j].c.offset = offset;
				RelocationEntries.push_back((char *)(&(mop[j].c.offset)) - StreamData);
				(*((float *)(StreamData+offset))) = objectives[i]->obj[j]->c;
				offset += 4;
			}
			else
			{
				mop[j].c.offset = 0;
			}
			if (objectives[i]->obj[j]->d)
			{
				mop[j].d.offset = offset;
				RelocationEntries.push_back((char *)(&(mop[j].d.offset)) - StreamData);
				(*((float *)(StreamData+offset))) = objectives[i]->obj[j]->d;
				offset += 4;
			}
			else
			{
				mop[j].d.offset = 0;
			}
			if (objectives[i]->obj[j]->e)
			{
				mop[j].e.offset = offset;
				RelocationEntries.push_back((char *)(&(mop[j].e.offset)) - StreamData);
				(*((float *)(StreamData+offset))) = objectives[i]->obj[j]->e;
				offset += 4;
			}
			else
			{
				mop[j].e.offset = 0;
			}
			mop[j].unknown = objectives[i]->obj[j]->unknown;
		}
		mo[i].bonus = objectives[i]->bonus;
	}
}
