/*
 *  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.
 *
 *  This program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "Be.h"


BMessage::BMessage () :
link (0),
fTarget (0),
fOriginal (0),
fChangeCount (0),
fCurSpecifier (0),
fPtrOffset (0),
fReplyRequired (false),
fReplyDone (false),
fIsReply (false),
fWasDelivered (false),
fReadOnly (false),
fHasSpecifiers (false),
what (0)
{
	fReplyTo.port = 0;
	fReplyTo.target = 0;
	fReplyTo.team = 0;
	fReplyTo.preferred = false;
}


BMessage::BMessage (uint32 what) :
link (0),
fTarget (0),
fOriginal (0),
fChangeCount (0),
fCurSpecifier (0),
fPtrOffset (0),
fReplyRequired (false),
fReplyDone (false),
fIsReply (false),
fWasDelivered (false),
fReadOnly (false),
fHasSpecifiers (false)
{
	this->what = what;
	fReplyTo.port = 0;
	fReplyTo.target = 0;
	fReplyTo.team = 0;
	fReplyTo.preferred = false;
}


// constructor
BMessage::BMessage (const BMessage& message) :
link (message.link),
fTarget (message.fTarget),
fOriginal (message.fOriginal),
fChangeCount (message.fChangeCount),
fPtrOffset (message.fPtrOffset),
fReplyRequired (message.fReplyRequired),
fReplyDone (message.fReplyDone),
fIsReply (message.fIsReply),
fWasDelivered (message.fWasDelivered),
fReadOnly (message.fReadOnly),
fHasSpecifiers (message.fHasSpecifiers)
{
	what = message.what;
	fReplyTo.port = message.fReplyTo.port;
	fReplyTo.target = message.fReplyTo.target;
	fReplyTo.team = message.fReplyTo.team;
	fReplyTo.preferred = message.fReplyTo.preferred;

	for (EntriesMapType::const_iterator i = message.fEntries.begin (); i != message.fEntries.end (); ++i) {
		winBe::MessageData* msgdata = new winBe::MessageData;
		msgdata->data_type = (*i).second->data_type;

		switch (msgdata->data_type) {

			case B_BOOL_TYPE:
			case B_INT8_TYPE:
			case B_INT16_TYPE:
			case B_INT32_TYPE:
			case B_POINTER_TYPE:
				msgdata->data = (*i).second->data;
				break;

			default:
				;
		}

		std::string name = (*i).first;
		fEntries.insert (std::make_pair (name, msgdata));
	}
}


// constructor
BMessage::BMessage (BMessage* a_message)
{
	what = a_message->what;
	//todo - copy 
}


// destructor
BMessage::~BMessage ()
{
	for (EntriesMapType::const_iterator i = fEntries.begin (); i != fEntries.end (); ++i) {
		switch ((*i).second->data_type) {

			case B_STRING_TYPE:
			case B_POINT_TYPE:
			case B_INT64_TYPE:
				delete (*i).second->data;
				break;

		}

		delete (*i).second;
	}

	fEntries.empty ();
}


// operator = BMessage
BMessage& BMessage::operator = (const BMessage &msg)
{
	what = msg.what;
	return *this;
}


// AddBool
status_t BMessage::AddBool (const char *name, bool val)
{
	winBe::MessageData* msgdata = new winBe::MessageData;
	msgdata->data_type = B_BOOL_TYPE;
	msgdata->data = reinterpret_cast<void*>(val);

	fEntries.insert (std::make_pair (std::string (name), msgdata));

	return B_OK;
}


// AddInt8
status_t BMessage::AddInt8 (const char *name, int8 val)
{
	winBe::MessageData* msgdata = new winBe::MessageData;
	msgdata->data_type = B_INT8_TYPE;
	msgdata->data = reinterpret_cast<void*>(val);

	fEntries.insert (std::make_pair (std::string (name), msgdata));

	return B_OK;
}


// AddInt16
status_t BMessage::AddInt16 (const char *name, int16 val)
{
	winBe::MessageData* msgdata = new winBe::MessageData;
	msgdata->data_type = B_INT16_TYPE;
	msgdata->data = reinterpret_cast<void*>(val);

	fEntries.insert (std::make_pair (std::string (name), msgdata));

	return B_OK;
}


// AddInt32
status_t BMessage::AddInt32 (const char *name, int32 val)
{
	winBe::MessageData* msgdata = new winBe::MessageData;
	msgdata->data_type = B_INT32_TYPE;
	msgdata->data = reinterpret_cast<void*>(val);

	fEntries.insert (std::make_pair (std::string (name), msgdata));

	return B_OK;
}


// AddFloat
status_t BMessage::AddFloat (const char *name, float val)
{
	winBe::MessageData* msgdata = new winBe::MessageData;
	msgdata->data_type = B_FLOAT_TYPE;
	msgdata->data = new float (val);

	fEntries.insert (std::make_pair (std::string (name), msgdata));

	return B_OK;
}


// AddInt64
status_t BMessage::AddInt64 (const char *name, int64 val)
{
	winBe::MessageData* msgdata = new winBe::MessageData;
	msgdata->data_type = B_INT64_TYPE;
	msgdata->data = new int64 (val);

	fEntries.insert (std::make_pair (std::string (name), msgdata));

	return B_OK;
}


// AddPoint
status_t BMessage::AddPoint (const char *name, BPoint a_point)
{
	winBe::MessageData* msgdata = new winBe::MessageData;
	msgdata->data_type = B_POINT_TYPE;
	msgdata->data = new BPoint (a_point);

	fEntries.insert (std::make_pair (std::string (name), msgdata));

	return B_OK;
}


// AddPointer
status_t BMessage::AddPointer (const char *name, const void* ptr)
{
	winBe::MessageData* msgdata = new winBe::MessageData;
	msgdata->data_type = B_POINTER_TYPE;
	msgdata->data = const_cast<void*>(ptr);

	fEntries.insert (std::make_pair (std::string (name), msgdata));

	return B_OK;
}


// AddMessage
status_t BMessage::AddMessage (const char *name, const BMessage* msg)
{
	winBe::MessageData* msgdata = new winBe::MessageData;
	msgdata->data_type = B_MESSAGE_TYPE;
	msgdata->data = const_cast<void*>(reinterpret_cast<const void*>(msg));

	fEntries.insert (std::make_pair (std::string (name), msgdata));

	return B_OK;
}


// AddString
status_t BMessage::AddString (const char *name, const char *a_string)
{
	winBe::MessageData* msgdata = new winBe::MessageData;
	msgdata->data_type = B_STRING_TYPE;
	msgdata->data = new std::string (a_string);

	fEntries.insert (std::make_pair (std::string (name), msgdata));

	return B_OK;
}


status_t BMessage::AddData (const char *name, type_code type, const void *data, ssize_t numBytes, bool is_fixed_size/* = true*/, int32 count/* = 1*/)
{
	return B_ERROR;
}


// FindPoint
status_t BMessage::FindPoint (const char *name, int32 index, BPoint *pt) const
{
	std::string namestr = name;
	status_t result = B_ERROR;
	
	for (std::multimap<std::string, winBe::MessageData*>::const_iterator i = fEntries.begin (); i != fEntries.end (); ++i) {
		if ((*i).first == namestr && (*i).second->data_type == B_POINT_TYPE) {
			*pt = *(reinterpret_cast<BPoint*>((*i).second->data));
			result = B_OK;
			break;
		}
	}

	return result;
}


// FindPoint
BPoint BMessage::FindPoint (const char *name, int32 n) const
{
	BPoint point;
	FindPoint (name, n, &point);
	return point;
}


// FindString
status_t BMessage::FindString (const char *name, int32 index, const char** str) const
{
	std::string namestr = name;
	status_t result = B_ERROR;
	
	for (std::multimap<std::string, winBe::MessageData*>::const_iterator i = fEntries.begin (); i != fEntries.end (); ++i) {
		if ((*i).first == namestr && (*i).second->data_type == B_STRING_TYPE) {
			*str = reinterpret_cast<const char*>((*i).second->data);
			result = B_OK;
			break;
		}
	}

	return result;
}


// FindString
status_t BMessage::FindString (const char *name, const char** str) const
{
	return FindString (name, 0, str);
}


// FindString
const char* BMessage::FindString (const char *name, int32 n) const
{
	const char* str;
	FindString (name, n, &str);
	return str;
}


// FindRect
status_t BMessage::FindRect (const char *name, int32 index, BRect* rect) const
{
	return 0;
}


// FindRect
BRect BMessage::FindRect (const char *name, int32 n) const
{
	BRect rect;
	FindRect (name, n, &rect);
	return rect;
}


// FindPointer
status_t BMessage::FindPointer (const char *name, int32 index, void **ptr) const
{
	*ptr = 0;
	std::string namestr = name;
	status_t result = B_ERROR;
	
	for (std::multimap<std::string, winBe::MessageData*>::const_iterator i = fEntries.begin (); i != fEntries.end (); ++i) {
		if ((*i).first == namestr && (*i).second->data_type == B_POINTER_TYPE) {
			*ptr = const_cast<void*>((*i).second->data);
			result = B_OK;
			break;
		}
	}

	return result;
}


// FindMessage
status_t BMessage::FindMessage (const char *name, BMessage *ptr) const
{
	//*ptr = 0;
	std::string namestr = name;
	status_t result = B_ERROR;
	
	for (std::multimap<std::string, winBe::MessageData*>::const_iterator i = fEntries.begin (); i != fEntries.end (); ++i) {
		if ((*i).first == namestr && (*i).second->data_type == B_MESSAGE_TYPE) {
			*ptr = reinterpret_cast<BMessage*>((*i).second->data);
			result = B_OK;
			break;
		}
	}

	return result;
}


// FindBool
status_t BMessage::FindBool (const char *name, int32 index, bool* value) const
{
	*value = false;
	std::string namestr = name;
	status_t result = B_ERROR;
	
	for (std::multimap<std::string, winBe::MessageData*>::const_iterator i = fEntries.begin (); i != fEntries.end (); ++i) {
		if ((*i).first == namestr && (*i).second->data_type == B_BOOL_TYPE) {
			*value = reinterpret_cast<bool>((*i).second->data);
			result = B_OK;
			break;
		}
	}

	return result;
}

// FindBool
status_t BMessage::FindBool (const char *name, bool* value) const
{
	return FindBool (name, 0, value);
}


// FindBool
bool BMessage::FindBool (const char *name, int32 n) const
{
	bool value;
	FindBool (name, n, &value);
	return value;
}


status_t BMessage::FindInt8 (const char *name, int32 index, int8* value) const
{
	*value = false;
	std::string namestr = name;
	status_t result = B_ERROR;
	
	for (std::multimap<std::string, winBe::MessageData*>::const_iterator i = fEntries.begin (); i != fEntries.end (); ++i) {
		if ((*i).first == namestr && (*i).second->data_type == B_INT8_TYPE) {
			*value = reinterpret_cast<int8>((*i).second->data);
			result = B_OK;
			break;
		}
	}

	return result;
}


status_t BMessage::FindInt8 (const char *name, int8* value) const
{
	return FindInt8 (name, 0, value);
}


status_t BMessage::FindInt32 (const char *name, int32 index, int32* value) const
{
	*value = false;
	std::string namestr = name;
	status_t result = B_ERROR;
	
	for (std::multimap<std::string, winBe::MessageData*>::const_iterator i = fEntries.begin (); i != fEntries.end (); ++i) {
		if ((*i).first == namestr && (*i).second->data_type == B_INT32_TYPE) {
			*value = reinterpret_cast<int32>((*i).second->data);
			result = B_OK;
			break;
		}
	}

	return result;
}


status_t BMessage::FindInt32 (const char *name, int32* value) const
{
	return FindInt32 (name, 0, value);
}


// FindInt32
int32 BMessage::FindInt32 (const char *name, int32 n) const
{
	int32 value;
	FindInt32 (name, n, &value);
	return value;
}


// FindFloat
status_t BMessage::FindFloat (const char *name, int32 index, float* value) const
{
	*value = false;
	std::string namestr = name;
	status_t result = B_ERROR;
	
	for (std::multimap<std::string, winBe::MessageData*>::const_iterator i = fEntries.begin (); i != fEntries.end (); ++i) {
		if ((*i).first == namestr && (*i).second->data_type == B_FLOAT_TYPE) {
			*value = *(static_cast<float*>((*i).second->data));
			result = B_OK;
			break;
		}
	}

	return result;
}


status_t BMessage::FindFloat (const char *name, float* value) const
{
	return FindFloat (name, 0, value);
}


// FindFloat
float BMessage::FindFloat (const char *name, int32 n) const
{
	float value;
	FindFloat (name, n, &value);
	return value;
}


status_t BMessage::FindData (const char *name, type_code type, const void **data, ssize_t *numBytes) const
{
	return B_ERROR;
}


status_t BMessage::ReplaceInt32 (const char *name, int32 val)
{
	return ReplaceInt32 (name, 0, val);
}


status_t BMessage::ReplaceInt32 (const char *name, int32 index, int32 val)
{
	return B_ERROR;
}


// _ReservedMessage1
void BMessage::_ReservedMessage1 ()
{
}


// _ReservedMessage2
void BMessage::_ReservedMessage2 ()
{
}


// _ReservedMessage3
void BMessage::_ReservedMessage3 ()
{
}
