/** 
 * @file llpanelplace.cpp
 * @brief Display of a place in the Find directory.
 *
 * $LicenseInfo:firstyear=2004&license=viewergpl$
 * 
 * Copyright (c) 2004-2009, Linden Research, Inc.
 * 
 * Second Life Viewer Source Code
 * The source code in this file ("Source Code") is provided by Linden Lab
 * to you under the terms of the GNU General Public License, version 2.0
 * ("GPL"), unless you have obtained a separate licensing agreement
 * ("Other License"), formally executed by you and Linden Lab.  Terms of
 * the GPL can be found in doc/GPL-license.txt in this distribution, or
 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
 * 
 * There are special exceptions to the terms and conditions of the GPL as
 * it is applied to this Source Code. View the full text of the exception
 * in the file doc/FLOSS-exception.txt in this software distribution, or
 * online at
 * http://secondlifegrid.net/programs/open_source/licensing/flossexception
 * 
 * By copying, modifying or distributing this software, you acknowledge
 * that you have read and understood your obligations described above,
 * and agree to abide by those obligations.
 * 
 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
 * COMPLETENESS OR PERFORMANCE.
 * $/LicenseInfo$
 */

#include "llviewerprecompiledheaders.h"

#include "llpanelplace.h"

#include "llviewercontrol.h"
#include "llqueryflags.h"
#include "llui.h"
#include "llsecondlifeurls.h"
#include "llfloater.h"
#include "llfloaterreg.h"
#include "llregionhandle.h"

#include "llagent.h"
#include "llviewerwindow.h"
#include "llbutton.h"
#include "llfloaterworldmap.h"
#include "lllineeditor.h"
#include "llnotificationsutil.h"
#include "lluiconstants.h"
#include "lltextbox.h"
#include "lltexteditor.h"
#include "lltexturectrl.h"
#include "lltrans.h"
#include "llworldmap.h"
#include "llviewerregion.h"
#include "llvoavatarself.h"
#include "lluictrlfactory.h"
//#include "llviewermenu.h"	// create_landmark()
#include "llweb.h"
#include "llsdutil.h"
#include "llsdutil_math.h"

LLPanelPlace::LLPanelPlace()
:	LLPanel(),
	mParcelID(),
	mRequestedID(),
	mRegionID(),
	mPosGlobal(),
	mPosRegion(),
	mAuctionID(0),
	mLandmarkAssetID()
{}

LLPanelPlace::~LLPanelPlace()
{
	if (mParcelID.notNull())
	{
		LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mParcelID, this);
	}
}

BOOL LLPanelPlace::postBuild()
{
	// Since this is only used in the directory browser, always
	// disable the snapshot control. Otherwise clicking on it will
	// open a texture picker.
	mSnapshotCtrl = getChild<LLTextureCtrl>("snapshot_ctrl");
	mSnapshotCtrl->setEnabled(FALSE);

    mNameEditor = getChild<LLTextBox>("name_editor");
	// Text boxes appear to have a " " in them by default.  This breaks the
	// emptiness test for filling in data from the network.  Slam to empty.
	mNameEditor->setText( LLStringUtil::null );

    mDescEditor = getChild<LLTextEditor>("desc_editor");

	mInfoEditor = getChild<LLTextBox>("info_editor");
	mLandTypeEditor = getChild<LLTextBox>("land_type_display");

    mLocationDisplay = getChild<LLTextBox>("location_editor");

	mTeleportBtn = getChild<LLButton>( "teleport_btn");
	mTeleportBtn->setClickedCallback(onClickTeleport, this);

	mMapBtn = getChild<LLButton>( "map_btn");
	mMapBtn->setClickedCallback(onClickMap, this);

	//mLandmarkBtn = getChild<LLButton>( "landmark_btn");
	//mLandmarkBtn->setClickedCallback(onClickLandmark, this);

	mAuctionBtn = getChild<LLButton>( "auction_btn");
	mAuctionBtn->setClickedCallback(onClickAuction, this);

	// Default to no auction button.  We'll show it if we get an auction id
	mAuctionBtn->setVisible(FALSE);

	// Temporary text to explain why the description panel is blank.
	// mDescEditor->setText("Parcel information not available without server update");

	return TRUE;
}

void LLPanelPlace::displayItemInfo(const LLInventoryItem* pItem)
{
	if (pItem)
	{
		mNameEditor->setText(pItem->getName());
		mDescEditor->setText(pItem->getDescription());
	}
}

// Use this for search directory clicks, because we are totally
// recycling the panel and don't need to use what's there.
//
// For SLURL clicks, don't call this, because we need to cache
// the location info from the user.
void LLPanelPlace::resetLocation()
{
	mParcelID.setNull();
	mRequestedID.setNull();
	mRegionID.setNull();
	mLandmarkAssetID.setNull();
	mPosGlobal.clearVec();
	mPosRegion.clearVec();
	mAuctionID = 0;
	mNameEditor->setText( LLStringUtil::null );
	mDescEditor->setText( LLStringUtil::null );
	mInfoEditor->setText( LLStringUtil::null );
	mLandTypeEditor->setText( LLStringUtil::null );
	mLocationDisplay->setText( LLStringUtil::null );
}


// Set the name and clear other bits of info.  Used for SLURL clicks
void LLPanelPlace::resetName(const std::string& name)
{
	setName(name);
	if(mDescEditor)
	{
		mDescEditor->setText( LLStringUtil::null );
	}
	if(mNameEditor)
	{
		llinfos << "Clearing place name" << llendl;
		mNameEditor->setText( LLStringUtil::null );
	}
	if(mInfoEditor)
	{
		mInfoEditor->setText( LLStringUtil::null );
	}
	if(mLandTypeEditor)
	{
		mLandTypeEditor->setText( LLStringUtil::null );
	}
}

//virtual
void LLPanelPlace::setParcelID(const LLUUID& parcel_id)
{
	mParcelID = parcel_id;
	sendParcelInfoRequest();
}

void LLPanelPlace::setSnapshot(const LLUUID& snapshot_id)
{
	mSnapshotCtrl->setImageAssetID(snapshot_id);
}

void LLPanelPlace::setLocationString(const std::string& location)
{
	mLocationDisplay->setText(location);
}

void LLPanelPlace::setLandTypeString(const std::string& land_type)
{
	mLandTypeEditor->setText(land_type);
}

void LLPanelPlace::sendParcelInfoRequest()
{
	if (mParcelID != mRequestedID)
	{
		LLRemoteParcelInfoProcessor::getInstance()->addObserver(mParcelID, this);
		LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(mParcelID);

		mRequestedID = mParcelID;
	}
}

//virtual
void LLPanelPlace::setErrorStatus(U32 status, const std::string& reason)
{
	// We only really handle 404 and 499 errors
	std::string error_text;
	if(status == 404)
	{
		error_text = getString("server_error_text");
	}
	else if(status == 499)
	{
		error_text = getString("server_forbidden_text");
	}
	mDescEditor->setText(error_text);
}

//virtual
void LLPanelPlace::processParcelInfo(const LLParcelData& parcel_data)
{
	mAuctionID = parcel_data.auction_id;

	if(parcel_data.snapshot_id.notNull())
	{
		mSnapshotCtrl->setImageAssetID(parcel_data.snapshot_id);
	}

	if( !parcel_data.name.empty()
	   && mNameEditor && mNameEditor->getText().empty())
	{
		mNameEditor->setText(parcel_data.name);
	}

	if( !parcel_data.desc.empty()
		&& mDescEditor && mDescEditor->getText().empty())
	{
		mDescEditor->setText(parcel_data.desc);
	}

	std::string info_text;
	LLUIString traffic = getString("traffic_text");
	traffic.setArg("[TRAFFIC]", llformat("%d ", (int)parcel_data.dwell));
	info_text = traffic;
	LLUIString area = getString("area_text");
	area.setArg("[AREA]", llformat("%d", parcel_data.actual_area));
	info_text += area;
	if (parcel_data.flags & DFQ_FOR_SALE)
	{
		LLUIString forsale = getString("forsale_text");
		forsale.setArg("[PRICE]", llformat("%d", parcel_data.sale_price));
		info_text += forsale;
	}
	if (parcel_data.auction_id != 0)
	{
		LLUIString auction = getString("auction_text");
		auction.setArg("[ID]", llformat("%010d ", parcel_data.auction_id));
		info_text += auction;
	}
	if (mInfoEditor)
	{
		mInfoEditor->setText(info_text);
	}

	// HACK: Flag 0x2 == adult region,
	// Flag 0x1 == mature region, otherwise assume PG
	std::string rating = LLViewerRegion::accessToString(SIM_ACCESS_PG);
	if (parcel_data.flags & 0x2)
	{
		rating = LLViewerRegion::accessToString(SIM_ACCESS_ADULT);
	}
	else if (parcel_data.flags & 0x1)
	{
		rating = LLViewerRegion::accessToString(SIM_ACCESS_MATURE);
	}

	// Just use given region position for display
	S32 region_x = llround(mPosRegion.mV[0]);
	S32 region_y = llround(mPosRegion.mV[1]);
	S32 region_z = llround(mPosRegion.mV[2]);

	// If the region position is zero, grab position from the global
	if(mPosRegion.isExactlyZero())
	{
		region_x = llround(parcel_data.global_x) % REGION_WIDTH_UNITS;
		region_y = llround(parcel_data.global_y) % REGION_WIDTH_UNITS;
		region_z = llround(parcel_data.global_z);
	}

	if(mPosGlobal.isExactlyZero())
	{
		mPosGlobal.setVec(parcel_data.global_x, parcel_data.global_y, parcel_data.global_z);
	}

	std::string location = llformat("%s %d, %d, %d (%s)",
									parcel_data.sim_name.c_str(), region_x, region_y, region_z, rating.c_str());
	if (mLocationDisplay)
	{
		mLocationDisplay->setText(location);
	}

	BOOL show_auction = (parcel_data.auction_id > 0);
	mAuctionBtn->setVisible(show_auction);
}


void LLPanelPlace::displayParcelInfo(const LLVector3& pos_region,
									 const LLUUID& landmark_asset_id,
									 const LLUUID& region_id,
									 const LLVector3d& pos_global)
{
	LLSD body;
	mPosRegion = pos_region;
	mPosGlobal = pos_global;
	mLandmarkAssetID = landmark_asset_id;
	std::string url = gAgent.getRegion()->getCapability("RemoteParcelRequest");
	if (!url.empty())
	{
		body["location"] = ll_sd_from_vector3(pos_region);
		if (!region_id.isNull())
		{
			body["region_id"] = region_id;
		}
		if (!pos_global.isExactlyZero())
		{
			U64 region_handle = to_region_handle(pos_global);
			body["region_handle"] = ll_sd_from_U64(region_handle);
		}
		LLHTTPClient::post(url, body, new LLRemoteParcelRequestResponder(getObserverHandle()));
	}
	else
	{
		mDescEditor->setText(getString("server_update_text"));
	}
	mSnapshotCtrl->setImageAssetID(LLUUID::null);
	mSnapshotCtrl->setFallbackImageName("default_land_picture.j2c");
}

// static
void LLPanelPlace::onClickTeleport(void* data)
{
	LLPanelPlace* self = (LLPanelPlace*)data;

	LLView* parent_viewp = self->getParent();
	LLFloater* parent_floaterp = dynamic_cast<LLFloater*>(parent_viewp);
	if (parent_floaterp)
	{
		parent_floaterp->closeFloater();
	}
	// LLFloater* parent_floaterp = (LLFloater*)self->getParent();
	parent_viewp->setVisible(false);
	LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance();
	if(self->mLandmarkAssetID.notNull() && worldmap_instance)
	{
		gAgent.teleportViaLandmark(self->mLandmarkAssetID);
		worldmap_instance->trackLandmark(self->mLandmarkAssetID);

	}
	else if (!self->mPosGlobal.isExactlyZero() && worldmap_instance)
	{
		gAgent.teleportViaLocation(self->mPosGlobal);
		worldmap_instance->trackLocation(self->mPosGlobal);
	}
}

// static
void LLPanelPlace::onClickMap(void* data)
{
	LLPanelPlace* self = (LLPanelPlace*)data;
	LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance();
	
	if (!self->mPosGlobal.isExactlyZero() && worldmap_instance)
	{
		worldmap_instance->trackLocation(self->mPosGlobal);
		LLFloaterReg::showInstance("world_map", "center");
	}
}

// static
/*
void LLPanelPlace::onClickLandmark(void* data)
{
	LLPanelPlace* self = (LLPanelPlace*)data;

	create_landmark(self->mNameEditor->getText(), "", self->mPosGlobal);
}
*/


// static
void LLPanelPlace::onClickAuction(void* data)
{
	LLPanelPlace* self = (LLPanelPlace*)data;
	LLSD args;
	args["AUCTION_ID"] = self->mAuctionID;

	LLNotificationsUtil::add("GoToAuctionPage", args);
}
/*
// static
bool LLPanelPlace::callbackAuctionWebPage(const LLSD& notification, const LLSD& response)
{
	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
	if (0 == option)
	{
		std::string url;
		url = LLNotifications::instance().getGlobalString("AUCTION_URL")  + llformat("%010d", response["auction_id"].asInteger());

		llinfos << "Loading auction page " << url << llendl;

		LLWeb::loadURL(url);
	}
	return false;
}
*/