void FSLSLBridge :: startCreation()
{
	////are we already in conversation with a bridge?
	////must have already received a URL call from a bridge.
	//if (mpBridge != NULL) 
	//{
	//	return;
	//}

	//if bridge object doesn't exist - create and attach it, update script.
	LLUUID catID = findFSCategory();

	LLViewerInventoryItem* fsBridge = findInvObject(mCurrentFullName, catID, LLAssetType::AT_OBJECT);
	if (fsBridge == NULL)
	{
		initCreationStep();
	}
	else
	{
		//TODO need versioning - see isOldBridgeVersion()
		mpBridge = fsBridge;
		if (!isItemAttached(mpBridge->getUUID()))
			LLAttachmentsMgr::instance().addAttachment(mpBridge->getUUID(), BRIDGE_POINT, FALSE, TRUE);			
	}
}
bool FSLSLBridge :: lslToViewer(std::string message, LLUUID fromID, LLUUID ownerID)
{
	if (!gSavedSettings.getBOOL("UseLSLBridge"))
		return false;

	llinfos << message << llendl;

	std::string tag = message.substr(0,11);

	if (tag == "<bridgeURL>")
	{
		// get the content of the message, between <tag> and </tag>
		mCurrentURL = message.substr(tag.length(), message.length() - ((tag.length() * 2) + 1));
		llinfos << "New URL is: " << mCurrentURL << llendl;
		
		if (mpBridge == NULL)
		{
			LLUUID catID = findFSCategory();
			LLViewerInventoryItem* fsBridge = findInvObject(mCurrentFullName, catID, LLAssetType::AT_OBJECT);

			if (fsBridge != NULL)
				mpBridge = fsBridge;
		}
		return viewerToLSL("URL Confirmed", new FSLSLBridgeRequestResponder());
	}
	return false;
}
void FSLSLBridge :: createNewBridge() 
{
	//check if user has a bridge
	LLUUID catID = findFSCategory();

	//attach the Linden rock from the library (will resize as soon as attached)
	LLUUID libID = gInventory.getLibraryRootFolderID();
	LLViewerInventoryItem* libRock = findInvObject(LIB_ROCK_NAME, libID, LLAssetType::AT_OBJECT);
	//shouldn't happen but just in case
	if (libRock != NULL)
	{
		//copy the library item to inventory and put it on 
		LLPointer<LLInventoryCallback> cb = new FSLSLBridgeRezCallback();
		copy_inventory_item(gAgent.getID(),libRock->getPermissions().getOwner(),libRock->getUUID(),catID,mCurrentFullName,cb);
	}
}
// Gets called by the Init, when inventory loaded.
void FSLSLBridge::startCreation()
{
	if (!isAgentAvatarValid())
	{
		llwarns << "AgentAvatar is not valid" << llendl;
		return;
	}

	llinfos << "startCreation called. gInventory.isInventoryUsable=" << gInventory.isInventoryUsable() << llendl;

	//if bridge object doesn't exist - create and attach it, update script.
	LLUUID catID = findFSCategory();

	LLViewerInventoryItem* fsBridge = findInvObject(mCurrentFullName, catID, LLAssetType::AT_OBJECT);

	//detach everything else
	detachOtherBridges();

	if (fsBridge == NULL)
	{
		llinfos << "Bridge not found in inventory, creating new one..." << llendl;
		initCreationStep();
	}
	else
	{
		//TODO need versioning - see isOldBridgeVersion()
		mpBridge = fsBridge;
		if (!isItemAttached(mpBridge->getUUID()))
		{
			if (!LLAppearanceMgr::instance().getIsInCOF(mpBridge->getUUID()))
			{
				//Is this a valid bridge - wear it. 
				LLAttachmentsMgr::instance().addAttachment(mpBridge->getUUID(), BRIDGE_POINT, FALSE, TRUE);	
				llinfos << "Bridge not attached but found in inventory, reattaching..." << llendl;
				//from here, the attach shoould report to ProcessAttach and make sure bridge is valid.
			}
			else
			{
				llinfos << "Bridge not found but in CoF. Waiting for automatic attach..." << llendl;
			}
		}
	}
}
//
//Bridge initialization
//
void FSLSLBridge :: recreateBridge()
{
	if (!gSavedSettings.getBOOL("UseLSLBridge"))
		return;

	LLUUID catID = findFSCategory();

	LLViewerInventoryItem* fsBridge = findInvObject(mCurrentFullName, catID, LLAssetType::AT_OBJECT);
	if (fsBridge != NULL)
	{
		if (get_is_item_worn(fsBridge->getUUID()))
		{
			LLVOAvatarSelf::detachAttachmentIntoInventory(fsBridge->getUUID());
		}
	}
	if (mpBridge != NULL)
		mpBridge = NULL; //the object itself will get cleaned up when new one is created.

	initCreationStep();
}
void FSLSLBridge::detachOtherBridges()
{
	LLUUID catID = findFSCategory();
	LLViewerInventoryCategory::cat_array_t cats;
	LLViewerInventoryItem::item_array_t items;

	LLViewerInventoryItem* fsBridge = findInvObject(mCurrentFullName, catID, LLAssetType::AT_OBJECT);

	//detach everything except current valid bridge - if any
	gInventory.collectDescendents(catID,cats,items,FALSE);

	for (S32 iIndex = 0; iIndex < items.count(); iIndex++)
	{
		const LLViewerInventoryItem* itemp = items.get(iIndex);
		if (get_is_item_worn(itemp->getUUID()) &&
			((fsBridge == NULL) || (itemp->getUUID() != fsBridge->getUUID())))
		{
			LLVOAvatarSelf::detachAttachmentIntoInventory(itemp->getUUID());
		}
	}
}
//
//Bridge initialization
//
void FSLSLBridge::recreateBridge()
{
	if (!gSavedSettings.getBOOL("UseLSLBridge"))
	{
		return;
	}

	if (gSavedSettings.getBOOL("NoInventoryLibrary"))
	{
		llwarns << "Asked to create bridge, but we don't have a library. Aborting." << llendl;
		reportToNearbyChat(LLTrans::getString("fsbridge_no_library"));
		mBridgeCreating = false;
		return;
	}

	if (mBridgeCreating)
	{
		llwarns << "Bridge creation already in progress, aborting new attempt." << llendl;
		reportToNearbyChat(LLTrans::getString("fsbridge_already_creating"));
		return;
	}

	LLUUID catID = findFSCategory();

	LLViewerInventoryItem* fsBridge = findInvObject(mCurrentFullName, catID, LLAssetType::AT_OBJECT);
	if (fsBridge != NULL)
	{
		if (get_is_item_worn(fsBridge->getUUID()))
		{
			LLVOAvatarSelf::detachAttachmentIntoInventory(fsBridge->getUUID());
		}
	}
	// clear the stored bridge ID - we are starting over.
	mpBridge = 0; //the object itself will get cleaned up when new one is created.

	initCreationStep();
}
void FSLSLBridge::createNewBridge()
{
	//check if user has a bridge
	LLUUID catID = findFSCategory();

	//attach the Linden rock from the library (will resize as soon as attached)
	LLUUID libID = gInventory.getLibraryRootFolderID();
	LLViewerInventoryItem* libRock = findInvObject(LIB_ROCK_NAME, libID, LLAssetType::AT_OBJECT);
	//shouldn't happen but just in case
	if (libRock != NULL)
	{
		//copy the library item to inventory and put it on 
		LLPointer<LLInventoryCallback> cb = new FSLSLBridgeRezCallback();
		llinfos << "Cloning a new Bridge container from the Library..." << llendl;
		copy_inventory_item(gAgent.getID(), libRock->getPermissions().getOwner(), libRock->getUUID(), catID, mCurrentFullName, cb);
	}
	else
	{
		llwarns << "Bridge container not found in the Library!" << llendl;
		// AH: Set to false or we won't be able to start another bridge creation
		// process in this session!
		mBridgeCreating = false;
	}
}
bool FSLSLBridge::lslToViewer(std::string message, LLUUID fromID, LLUUID ownerID)
{
	if (!gSavedSettings.getBOOL("UseLSLBridge"))
	{
		return false;
	}

	lldebugs << message << llendl;
	
	//<FS:TS> FIRE-962: Script controls for built-in AO
	if ((message[0]) != '<')
	{
		return false; 		// quick exit if no leading <
	}
	S32 closebracket = message.find('>');
	S32 firstblank = message.find(' ');
	S32 tagend;
	if (closebracket == std::string::npos)
	{
		tagend = firstblank;
	}
	else if (firstblank == std::string::npos)
	{
		tagend = closebracket;
	}
	else
	{
		tagend = (closebracket < firstblank) ? closebracket : firstblank;
	}
	if (tagend == std::string::npos)
	{
		return false;
	}
	std::string tag = message.substr(0, tagend + 1);
	std::string ourBridge = gSavedPerAccountSettings.getString("FSLSLBridgeUUID");
	//</FS:TS> FIRE-962
	
	bool status = false;
	if (tag == "<bridgeURL>")
	{

		// brutish parsing
		S32 urlStart  = message.find("<bridgeURL>") + 11;
		S32 urlEnd    = message.find("</bridgeURL>");
		S32 authStart = message.find("<bridgeAuth>") + 12;
		S32 authEnd   = message.find("</bridgeAuth>");
		S32 verStart  = message.find("<bridgeVer>") + 11;
		S32 verEnd    = message.find("</bridgeVer>");
		std::string bURL = message.substr(urlStart,urlEnd - urlStart);
		std::string bAuth = message.substr(authStart,authEnd - authStart);
		std::string bVer = message.substr(verStart,verEnd - verStart);

		// Verify Version
		// todo

		// Verify Authorization
		if (ourBridge != bAuth)
		{
			llwarns << "BridgeURL message received from ("<< bAuth <<") , but not from our registered bridge ("<< ourBridge <<"). Ignoring." << llendl;
			// Failing bridge authorization automatically kicks off a bridge rebuild. This correctly handles the
			// case where a user logs in from multiple computers which cannot have the bridgeAuth ID locally 
			// synchronized.
			
			
			// If something that looks like our current bridge is attached but failed auth, detach and recreate.
			LLUUID catID = findFSCategory();
			LLViewerInventoryItem* fsBridge = findInvObject(mCurrentFullName, catID, LLAssetType::AT_OBJECT);
			if (fsBridge != NULL)
			{
				if (get_is_item_worn(fsBridge->getUUID()))
				{
					LLVOAvatarSelf::detachAttachmentIntoInventory(fsBridge->getUUID());
					//This may have been an unfinished bridge. If so - stop the process before recreating.
					if (mBridgeCreating)
						mBridgeCreating = false;
					recreateBridge();
					return true; 
				}
			}
			
			// If something that didn't look like our current bridge failed auth, don't recreate, it might interfere with a bridge creation in progress
			// or normal bridge startup.  Bridge creation isn't threadsafe yet.
			return true;
		}

		// Save the inworld UUID of this attached bridge for later checking
		mBridgeUUID = fromID;
		
		// Get URL
		mCurrentURL = bURL;
		llinfos << "New Bridge URL is: " << mCurrentURL << llendl;
		
		if (mpBridge == NULL)
		{
			LLUUID catID = findFSCategory();
			LLViewerInventoryItem* fsBridge = findInvObject(mCurrentFullName, catID, LLAssetType::AT_OBJECT);
			mpBridge = fsBridge;
		}

		status = viewerToLSL("URL Confirmed", new FSLSLBridgeRequestResponder());
		//updateBoolSettingValue("UseLSLFlightAssist");
		if (!mIsFirstCallDone)
		{
			//on first call from bridge, confirm that we are here
			//then check options use
			updateBoolSettingValue("UseLSLFlightAssist");
			updateBoolSettingValue("FSPublishRadarTag");
			mIsFirstCallDone = true;
		}
		return true;
	}
	
	//<FS:TS> FIRE-962: Script controls for built-in AO
	if (fromID != mBridgeUUID)
	{
		return false;		// ignore if not from the bridge
	}
	if (tag == "<clientAO ")
	{
		status = true;
		S32 valuepos = message.find("state=") + 6;
		if (valuepos != std::string::npos)
		{
			if (message.substr(valuepos, 2) == "on")
			{
				gSavedPerAccountSettings.setBOOL("UseAO", TRUE);
			}
			else if (message.substr(valuepos, 3) == "off")
			{
				gSavedPerAccountSettings.setBOOL("UseAO", FALSE);
			}
		}
	}
	//</FS:TS> FIRE-962
	return status;
}