/** 
* @file llpathfindingobject.cpp
* @brief Implementation of llpathfindingobject
* @author Stinson@lindenlab.com
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
* $/LicenseInfo$
*/


#include "llviewerprecompiledheaders.h"

#include "llpathfindingobject.h"

#include <string>

#include "llavatarname.h"
#include "llavatarnamecache.h"
#include "llsd.h"
#include "lluuid.h"
#include "v3math.h"

#define PATHFINDING_OBJECT_NAME_FIELD           "name"
#define PATHFINDING_OBJECT_DESCRIPTION_FIELD    "description"
#define PATHFINDING_OBJECT_OWNER_FIELD          "owner"
#define PATHFINDING_OBJECT_POSITION_FIELD       "position"
#define PATHFINDING_OBJECT_IS_GROUP_OWNED_FIELD "owner_is_group"

//---------------------------------------------------------------------------
// LLPathfindingObject
//---------------------------------------------------------------------------

LLPathfindingObject::LLPathfindingObject()
	: mUUID(),
	mName(),
	mDescription(),
	mOwnerUUID(),
	mHasOwnerName(false),
	mOwnerName(),
	mAvatarNameCacheConnection(),
	mIsGroupOwned(false),
	mLocation(),
	mOwnerNameSignal()
{
}

LLPathfindingObject::LLPathfindingObject(const std::string &pUUID, const LLSD &pObjectData)
	: mUUID(pUUID),
	mName(),
	mDescription(),
	mOwnerUUID(),
	mHasOwnerName(false),
	mOwnerName(),
	mAvatarNameCacheConnection(),
	mIsGroupOwned(false),
	mLocation(),
	mOwnerNameSignal()
{
	parseObjectData(pObjectData);
}

LLPathfindingObject::LLPathfindingObject(const LLPathfindingObject& pOther)
	: mUUID(pOther.mUUID),
	mName(pOther.mName),
	mDescription(pOther.mDescription),
	mOwnerUUID(pOther.mOwnerUUID),
	mHasOwnerName(false),
	mOwnerName(),
	mAvatarNameCacheConnection(),
	mIsGroupOwned(pOther.mIsGroupOwned),
	mLocation(pOther.mLocation),
	mOwnerNameSignal()
{
	fetchOwnerName();
}

LLPathfindingObject::~LLPathfindingObject()
{
	disconnectAvatarNameCacheConnection();
}

LLPathfindingObject &LLPathfindingObject::operator =(const LLPathfindingObject& pOther)
{
	mUUID = pOther.mUUID;
	mName = pOther.mName;
	mDescription = pOther.mDescription;
	mOwnerUUID = pOther.mOwnerUUID;
	fetchOwnerName();
	mIsGroupOwned = pOther.mIsGroupOwned;
	mLocation = pOther.mLocation;

	return *this;
}

std::string LLPathfindingObject::getOwnerName() const
{
	std::string ownerName;

	if (hasOwner())
	{
		ownerName = mOwnerName.getCompleteName();
	}

	return ownerName;
}

LLPathfindingObject::name_connection_t LLPathfindingObject::registerOwnerNameListener(name_callback_t pOwnerNameCallback)
{
	llassert(hasOwner());

	name_connection_t connection;
	if (hasOwnerName())
	{
		pOwnerNameCallback(this);
	}
	else
	{
		connection = mOwnerNameSignal.connect(pOwnerNameCallback);
	}

	return connection;
}

void LLPathfindingObject::parseObjectData(const LLSD &pObjectData)
{
	llassert(pObjectData.has(PATHFINDING_OBJECT_NAME_FIELD));
	llassert(pObjectData.get(PATHFINDING_OBJECT_NAME_FIELD).isString());
	mName = pObjectData.get(PATHFINDING_OBJECT_NAME_FIELD).asString();
	
	llassert(pObjectData.has(PATHFINDING_OBJECT_DESCRIPTION_FIELD));
	llassert(pObjectData.get(PATHFINDING_OBJECT_DESCRIPTION_FIELD).isString());
	mDescription = pObjectData.get(PATHFINDING_OBJECT_DESCRIPTION_FIELD).asString();

	llassert(pObjectData.has(PATHFINDING_OBJECT_OWNER_FIELD));
	llassert(pObjectData.get(PATHFINDING_OBJECT_OWNER_FIELD).isUUID());
	mOwnerUUID = pObjectData.get(PATHFINDING_OBJECT_OWNER_FIELD).asUUID();
	fetchOwnerName();

	if (pObjectData.has(PATHFINDING_OBJECT_IS_GROUP_OWNED_FIELD))
	{
		llassert(pObjectData.get(PATHFINDING_OBJECT_IS_GROUP_OWNED_FIELD).isBoolean());
		mIsGroupOwned = pObjectData.get(PATHFINDING_OBJECT_IS_GROUP_OWNED_FIELD).asBoolean();
	}

	llassert(pObjectData.has(PATHFINDING_OBJECT_POSITION_FIELD));
	llassert(pObjectData.get(PATHFINDING_OBJECT_POSITION_FIELD).isArray());
	mLocation.setValue(pObjectData.get(PATHFINDING_OBJECT_POSITION_FIELD));
}

void LLPathfindingObject::fetchOwnerName()
{
	mHasOwnerName = false;
	if (hasOwner())
	{
		mHasOwnerName = LLAvatarNameCache::get(mOwnerUUID, &mOwnerName);
		if (!mHasOwnerName)
		{
			disconnectAvatarNameCacheConnection();
			mAvatarNameCacheConnection = LLAvatarNameCache::get(mOwnerUUID, boost::bind(&LLPathfindingObject::handleAvatarNameFetch, this, _1, _2));
		}
	}
}

void LLPathfindingObject::handleAvatarNameFetch(const LLUUID &pOwnerUUID, const LLAvatarName &pAvatarName)
{
	llassert(mOwnerUUID == pOwnerUUID);

	mOwnerName = pAvatarName;
	mHasOwnerName = true;

	disconnectAvatarNameCacheConnection();

	mOwnerNameSignal(this);
}

void LLPathfindingObject::disconnectAvatarNameCacheConnection()
{
	if (mAvatarNameCacheConnection.connected())
	{
		mAvatarNameCacheConnection.disconnect();
	}
}