/** 
 * @file llfloaterbuycurrency.cpp
 * @brief LLFloaterBuyCurrency class implementation
 *
 * Copyright (c) 2005-$CurrentYear$, Linden Research, Inc.
 * $License$
 */

#include "llviewerprecompiledheaders.h"

#include "llfloaterbuycurrency.h"

// viewer includes
#include "llcurrencyuimanager.h"
#include "llfloater.h"
#include "llstatusbar.h"
#include "lltextbox.h"
#include "llviewchildren.h"
#include "llviewerwindow.h"
#include "llvieweruictrlfactory.h"
#include "llweb.h"
#include "llwindow.h"
#include "viewer.h"

static const S32 STANDARD_BUY_AMOUNT = 1000;
static const S32 MINIMUM_BALANCE_AMOUNT = 0;

class LLFloaterBuyCurrencyUI
:	public LLFloater
{
public:
	static LLFloaterBuyCurrencyUI* soleInstance(bool createIfNeeded);

private:
	static LLFloaterBuyCurrencyUI* sInstance;

	LLFloaterBuyCurrencyUI();
	virtual ~LLFloaterBuyCurrencyUI();


public:
	LLViewChildren		mChildren;
	LLCurrencyUIManager	mManager;
	
	bool		mHasTarget;
	std::string	mTargetName;
	S32			mTargetPrice;
	
public:
	void noTarget();
	void target(const std::string& name, S32 price);
	
	virtual BOOL postBuild();
	
	void updateUI();

	virtual void draw();
	virtual BOOL canClose();
	virtual void onClose(bool app_quitting);

	static void onClickBuy(void* data);
	static void onClickCancel(void* data);
	static void onClickErrorWeb(void* data);
};


// static
LLFloaterBuyCurrencyUI* LLFloaterBuyCurrencyUI::sInstance = NULL;

// static
LLFloaterBuyCurrencyUI* LLFloaterBuyCurrencyUI::soleInstance(bool createIfNeeded)
{
	if (!sInstance  &&  createIfNeeded)
	{
		sInstance = new LLFloaterBuyCurrencyUI();

		gUICtrlFactory->buildFloater(sInstance, "floater_buy_currency.xml");
		sInstance->center();
	}
	
	return sInstance;
}


#if LL_WINDOWS
// passing 'this' during construction generates a warning. The callee
// only uses the pointer to hold a reference to 'this' which is
// already valid, so this call does the correct thing. Disable the
// warning so that we can compile without generating a warning.
#pragma warning(disable : 4355)
#endif 
LLFloaterBuyCurrencyUI::LLFloaterBuyCurrencyUI()
:	LLFloater("Buy Currency"),
	mChildren(*this),
	mManager(*this)
{
}

LLFloaterBuyCurrencyUI::~LLFloaterBuyCurrencyUI()
{
	if (sInstance == this)
	{
		sInstance = NULL;
	}
}


void LLFloaterBuyCurrencyUI::noTarget()
{
	mHasTarget = false;
	mManager.setAmount(STANDARD_BUY_AMOUNT);
}

void LLFloaterBuyCurrencyUI::target(const std::string& name, S32 price)
{
	mHasTarget = true;
	mTargetName = name;
	mTargetPrice = price;
	
	S32 balance = gStatusBar->getBalance();
	S32 need = price - balance;
	if (need < 0)
	{
		need = 0;
	}
	
	mManager.setAmount(need + MINIMUM_BALANCE_AMOUNT);
}


// virtual
BOOL LLFloaterBuyCurrencyUI::postBuild()
{
	mManager.prepare();
	
	childSetAction("buy_btn", onClickBuy, this);
	childSetAction("cancel_btn", onClickCancel, this);
	childSetAction("error_web", onClickErrorWeb, this);

	updateUI();
	
	return TRUE;
}

void LLFloaterBuyCurrencyUI::draw()
{
	if (mManager.process())
	{
		if (mManager.bought())
		{
			close();
			return;
		}
		
		updateUI();
	}

	LLFloater::draw();
}

BOOL LLFloaterBuyCurrencyUI::canClose()
{
	return mManager.canCancel();
}

void LLFloaterBuyCurrencyUI::onClose(bool app_quitting)
{
	LLFloater::onClose(app_quitting);
	delete this;
}

void LLFloaterBuyCurrencyUI::updateUI()
{
	bool hasError = mManager.hasError();
	mManager.updateUI(!hasError && !mManager.buying());

	// section zero: title area
	{
		childSetVisible("info_buying", false);
		childSetVisible("info_cannot_buy", false);
		childSetVisible("info_need_more", false);
		if (hasError)
		{
			childSetVisible("info_cannot_buy", true);
		}
		else if (mHasTarget)
		{
			childSetVisible("info_need_more", true);
		}
		else
		{
			childSetVisible("info_buying", true);
		}
	}
	
	// error section
	if (hasError)
	{
		mChildren.setBadge("step_error", LLViewChildren::BADGE_ERROR);
		
		LLTextBox* message = LLUICtrlFactory::getTextBoxByName(this, "error_message");
		if (message)
		{
			message->setVisible(true);
			message->setWrappedText(mManager.errorMessage());
		}

		childSetVisible("error_web", !mManager.errorURI().empty());
	}
	else
	{
		childHide("step_error");
		childHide("error_message");
		childHide("error_web");
	}
	
	
	//  currency
	childSetVisible("contacting", false);
	childSetVisible("buy_action", false);
	childSetVisible("buy_action_unknown", false);
	
	if (!hasError)
	{
		mChildren.setBadge("step_1", LLViewChildren::BADGE_NOTE);

		if (mManager.buying())
		{
			childSetVisible("contacting", true);
		}
		else
		{
			if (mHasTarget)
			{
				childSetVisible("buy_action", true);
				childSetTextArg("buy_action", "[NAME]", mTargetName);
				childSetTextArg("buy_action", "[PRICE]", llformat("%d",mTargetPrice));
			}
			else
			{
				childSetVisible("buy_action_unknown", true);
			}
		}
		
		S32 balance = gStatusBar->getBalance();
		childShow("balance_label");
		childShow("balance_amount");
		childSetTextArg("balance_amount", "[AMT]", llformat("%d", balance));
		
		S32 buying = mManager.getAmount();
		childShow("buying_label");
		childShow("buying_amount");
		childSetTextArg("buying_amount", "[AMT]", llformat("%d", buying));
		
		S32 total = balance + buying;
		childShow("total_label");
		childShow("total_amount");
		childSetTextArg("total_amount", "[AMT]", llformat("%d", total));

		childSetVisible("purchase_warning_repurchase", false);
		childSetVisible("purchase_warning_notenough", false);
		if (mHasTarget)
		{
			if (total >= mTargetPrice)
			{
				childSetVisible("purchase_warning_repurchase", true);
			}
			else
			{
				childSetVisible("purchase_warning_notenough", true);
			}
		}
	}
	else
	{
		childHide("step_1");
		childHide("balance_label");
		childHide("balance_amount");
		childHide("buying_label");
		childHide("buying_amount");
		childHide("total_label");
		childHide("total_amount");
		childHide("purchase_warning_repurchase");
		childHide("purchase_warning_notenough");
	}
	
	childSetEnabled("buy_btn", mManager.canBuy());
}

// static
void LLFloaterBuyCurrencyUI::onClickBuy(void* data)
{
	LLFloaterBuyCurrencyUI* self = LLFloaterBuyCurrencyUI::soleInstance(false);
	if (self)
	{
		self->mManager.buy();
		self->updateUI();
		// JC: updateUI() doesn't get called again until progress is made
		// with transaction processing, so the "Purchase" button would be
		// left enabled for some time.  Pre-emptively disable.
		self->childSetEnabled("buy_btn", false);
	}
}

// static
void LLFloaterBuyCurrencyUI::onClickCancel(void* data)
{
	LLFloaterBuyCurrencyUI* self = LLFloaterBuyCurrencyUI::soleInstance(false);
	if (self)
	{
		self->close();
	}
}

// static
void LLFloaterBuyCurrencyUI::onClickErrorWeb(void* data)
{
	LLFloaterBuyCurrencyUI* self = LLFloaterBuyCurrencyUI::soleInstance(false);
	if (self)
	{
		LLWeb::loadURLExternal(self->mManager.errorURI());
		self->close();
	}
}

// static
void LLFloaterBuyCurrency::buyCurrency()
{
	if (gHideLinks)
	{
		return;
	}

	LLFloaterBuyCurrencyUI* ui = LLFloaterBuyCurrencyUI::soleInstance(true);
	ui->noTarget();
	ui->updateUI();
	ui->open();
}

void LLFloaterBuyCurrency::buyCurrency(const std::string& name, S32 price)
{
	if (gHideLinks)
	{
		LLStringBase<char>::format_map_t args;
		args["[NAME]"] = name.c_str();
		args["[PRICE]"] = price;
		gViewerWindow->alertXml("NotEnoughCurrency", args);
		return;
	}
	
	LLFloaterBuyCurrencyUI* ui = LLFloaterBuyCurrencyUI::soleInstance(true);
	ui->target(name, price);
	ui->updateUI();
	ui->open();
}

