// static
void LLFloaterMessageLog::conditionalLog(LLFloaterMessageLogItem item)
{	
	if(!sBusyApplyingFilter)
		sInstance->childSetText("log_status_text", llformat("Showing %d messages from %d", sFloaterMessageLogItems.size(), sMessageLogEntries.size()));
	std::string find_name = item.mName;
	LLStringUtil::toLower(find_name);
	if(sMessageLogFilter.mPositiveNames.size())
		if(std::find(sMessageLogFilter.mPositiveNames.begin(), sMessageLogFilter.mPositiveNames.end(), find_name) == sMessageLogFilter.mPositiveNames.end())
			return;
	if(std::find(sMessageLogFilter.mNegativeNames.begin(), sMessageLogFilter.mNegativeNames.end(), find_name) != sMessageLogFilter.mNegativeNames.end())
		return;
	sFloaterMessageLogItems.push_back(item); // moved from beginning...
	BOOL outgoing = item.isOutgoing();
	std::string net_name("\?\?\?");
	if(item.mType == LLFloaterMessageLogItem::TEMPLATE)
	{
		LLHost find_host = outgoing ? item.mToHost : item.mFromHost;
		net_name = find_host.getIPandPort();
		std::list<LLNetListItem*>::iterator end = sNetListItems.end();
		for(std::list<LLNetListItem*>::iterator iter = sNetListItems.begin(); iter != end; ++iter)
		{
			if((*iter)->mCircuitData->getHost() == find_host)
			{
				net_name = (*iter)->mName;
				break;
			}
		}
	}
	LLSD element;
	element["id"] = item.mID;
	LLSD& sequence_column = element["columns"][0];
	sequence_column["column"] = "sequence";
	sequence_column["value"] = llformat("%u", item.mSequenceID);
	LLSD& type_column = element["columns"][1];
	type_column["column"] = "type";
	type_column["value"] = item.mType == LLFloaterMessageLogItem::TEMPLATE ? "UDP" : "\?\?\?";
	LLSD& direction_column = element["columns"][2];
	direction_column["column"] = "direction";
	direction_column["value"] = outgoing ? "to" : "from";
	LLSD& net_column = element["columns"][3];
	net_column["column"] = "net";
	net_column["value"] = net_name;
	LLSD& name_column = element["columns"][4];
	name_column["column"] = "name";
	name_column["value"] = item.mName;
	/*
	LLSD& zer_column = element["columns"][5];
	zer_column["column"] = "flag_zer";
	zer_column["type"] = "icon";
	zer_column["value"] = (item.mFlags & LL_ZERO_CODE_FLAG) ? "flag_zer.tga" : "";
	LLSD& rel_column = element["columns"][6];
	rel_column["column"] = "flag_rel";
	rel_column["type"] = "icon";
	rel_column["value"] = (item.mFlags & LL_RELIABLE_FLAG) ? "flag_rel.tga" : "";
	LLSD& rsd_column = element["columns"][7];
	rsd_column["column"] = "flag_rsd";
	rsd_column["type"] = "icon";
	rsd_column["value"] = (item.mFlags & LL_RESENT_FLAG) ? "flag_rsd.tga" : "";
	LLSD& ack_column = element["columns"][8];
	ack_column["column"] = "flag_ack";
	ack_column["type"] = "icon";
	ack_column["value"] = (item.mFlags & LL_ACK_FLAG) ? "flag_ack.tga" : "";
	*/
	LLSD& summary_column = element["columns"][5];
	summary_column["column"] = "summary";
	summary_column["value"] = item.mSummary;
	LLScrollListCtrl* scrollp = sInstance->getChild<LLScrollListCtrl>("message_log");
	S32 scroll_pos = scrollp->getScrollPos();
	scrollp->addElement(element);
	if(scroll_pos > scrollp->getItemCount() - scrollp->getPageLines() - 4)
		scrollp->setScrollPos(scrollp->getItemCount());
}
void LLFloaterMessageLog::refreshNetList()
{
	LLScrollListCtrl* scrollp = getChild<LLScrollListCtrl>("net_list");
	// Update circuit data of net list items
	std::vector<LLCircuitData*> circuits = gMessageSystem->mCircuitInfo.getCircuitDataList();
	std::vector<LLCircuitData*>::iterator circuits_end = circuits.end();
	for(std::vector<LLCircuitData*>::iterator iter = circuits.begin(); iter != circuits_end; ++iter)
	{
		LLNetListItem* itemp = findNetListItem((*iter)->getHost());
		if(!itemp)
		{
			LLUUID id; id.generate();
			itemp = new LLNetListItem(id);
			sNetListItems.push_back(itemp);
		}
		itemp->mCircuitData = (*iter);
	}
	// Clear circuit data of items whose circuits are gone
	std::list<LLNetListItem*>::iterator items_end = sNetListItems.end();
	for(std::list<LLNetListItem*>::iterator iter = sNetListItems.begin(); iter != items_end; ++iter)
	{
		if(std::find(circuits.begin(), circuits.end(), (*iter)->mCircuitData) == circuits.end())
			(*iter)->mCircuitData = NULL;
	}
	// Remove net list items that are totally useless now
	for(std::list<LLNetListItem*>::iterator iter = sNetListItems.begin(); iter != sNetListItems.end();)
	{
		if((*iter)->mCircuitData == NULL)
			iter = sNetListItems.erase(iter);
		else ++iter;
	}
	// Update names of net list items
	items_end = sNetListItems.end();
	for(std::list<LLNetListItem*>::iterator iter = sNetListItems.begin(); iter != items_end; ++iter)
	{
		LLNetListItem* itemp = (*iter);
		if(itemp->mAutoName)
		{
			if(itemp->mCircuitData)
			{
				LLViewerRegion* regionp = LLWorld::getInstance()->getRegion(itemp->mCircuitData->getHost());
				if(regionp)
				{
					std::string name = regionp->getName();
					if(name == "") name = llformat("%s (awaiting region name)", itemp->mCircuitData->getHost().getString().c_str());
					itemp->mName = name;
					itemp->mPreviousRegionName = name;
				}
				else
				{
					itemp->mName = itemp->mCircuitData->getHost().getString();
					if(itemp->mPreviousRegionName != "")
						itemp->mName.append(llformat(" (was %s)", itemp->mPreviousRegionName.c_str()));
				}
			}
			else
			{
				// an item just for an event queue, not handled yet
				itemp->mName = "Something else";
			}
		}
	}
	// Rebuild scroll list from scratch
	LLUUID selected_id = scrollp->getFirstSelected() ? scrollp->getFirstSelected()->getUUID() : LLUUID::null;
	S32 scroll_pos = scrollp->getScrollPos();
	scrollp->clearRows();
	for(std::list<LLNetListItem*>::iterator iter = sNetListItems.begin(); iter != items_end; ++iter)
	{
		LLNetListItem* itemp = (*iter);
		LLSD element;
		element["id"] = itemp->mID;
		LLSD& text_column = element["columns"][0];
		text_column["column"] = "text";
		text_column["value"] = itemp->mName + (itemp->mCircuitData->getHost() == gAgent.getRegionHost() ? " (main)" : "");
		for(int i = 0; i < 2; i++)
		{
			LLSD& icon_column = element["columns"][i + 1];
			icon_column["column"] = llformat("icon%d", i);
			icon_column["type"] = "icon";
			icon_column["value"] = "";
		}
		LLScrollListItem* scroll_itemp = scrollp->addElement(element);
		BOOL has_live_circuit = itemp->mCircuitData && itemp->mCircuitData->isAlive();
		if(has_live_circuit)
		{
			LLScrollListIcon* icon = (LLScrollListIcon*)scroll_itemp->getColumn(1);
			icon->setValue("icon_net_close_circuit.tga");
			icon->setClickCallback(boost::bind(&LLFloaterMessageLog::onClickCloseCircuit, itemp));
		}
		else
		{
			LLScrollListIcon* icon = (LLScrollListIcon*)scroll_itemp->getColumn(1);
			icon->setValue("icon_net_close_circuit_gray.tga");
			//icon->setClickCallback(NULL);
		}
		// Event queue isn't even supported yet... FIXME
		LLScrollListIcon* icon = (LLScrollListIcon*)scroll_itemp->getColumn(2);
		icon->setValue("icon_net_close_eventpoll_gray.tga");
		//icon->setClickCallback(NULL);
	}
	if(selected_id.notNull()) scrollp->selectByID(selected_id);
	if(scroll_pos < scrollp->getItemCount()) scrollp->setScrollPos(scroll_pos);
}
// static
BOOL LLFloaterExploreSounds::tick()
{
    //if(childGetValue("pause_chk").asBoolean()) return FALSE;

    bool show_collision_sounds = childGetValue("collision_chk").asBoolean();
    bool show_repeated_assets = childGetValue("repeated_asset_chk").asBoolean();
    bool show_avatars = childGetValue("avatars_chk").asBoolean();
    bool show_objects = childGetValue("objects_chk").asBoolean();

    std::list<LLSoundHistoryItem> history;
    if(childGetValue("pause_chk").asBoolean())
    {
        history = mLastHistory;
    }
    else
    {
        std::map<LLUUID, LLSoundHistoryItem>::iterator map_iter = gSoundHistory.begin();
        std::map<LLUUID, LLSoundHistoryItem>::iterator map_end = gSoundHistory.end();
        for( ; map_iter != map_end; ++map_iter)
        {
            history.push_back((*map_iter).second);
        }
        LLSoundHistoryItemCompare c;
        history.sort(c);
        mLastHistory = history;
    }

    LLScrollListCtrl* list = getChild<LLScrollListCtrl>("sound_list");

    // Save scroll pos and selection so they can be restored
    S32 scroll_pos = list->getScrollPos();
    uuid_vec_t selected_ids = list->getSelectedIDs();
    list->clearRows();

    std::list<LLUUID> unique_asset_list;

    std::list<LLSoundHistoryItem>::iterator iter = history.begin();
    std::list<LLSoundHistoryItem>::iterator end = history.end();
    for( ; iter != end; ++iter)
    {
        LLSoundHistoryItem item = (*iter);

        bool is_avatar = item.mOwnerID == item.mSourceID;
        if(is_avatar && !show_avatars) continue;

        bool is_object = !is_avatar;
        if(is_object && !show_objects) continue;

        bool is_repeated_asset = std::find(unique_asset_list.begin(), unique_asset_list.end(), item.mAssetID) != unique_asset_list.end();
        if(is_repeated_asset && !show_repeated_assets) continue;

        if(!item.mReviewed)
        {
            item.mReviewedCollision	= std::find(&collision_sounds[0], &collision_sounds[num_collision_sounds], item.mAssetID) != &collision_sounds[num_collision_sounds];
            item.mReviewed = true;
        }
        bool is_collision_sound = item.mReviewedCollision;
        if(is_collision_sound && !show_collision_sounds) continue;

        unique_asset_list.push_back(item.mAssetID);

        LLSD element;
        element["id"] = item.mID;

        LLSD& playing_column = element["columns"][0];
        playing_column["column"] = "playing";
        if(item.isPlaying())
        {
            playing_column["value"] = item.mIsLooped ? " Looping" : " Playing";
        }
        else
        {
            S32 time = (LLTimer::getElapsedSeconds() - item.mTimeStopped);
            S32 hours = time / 3600;
            S32 mins = time / 60;
            S32 secs = time % 60;
            playing_column["value"] = llformat("%d:%02d:%02d", hours,mins,secs);
        }

        LLSD& type_column = element["columns"][1];
        type_column["column"] = "type";
        type_column["type"] = "icon";
        if(item.mType == LLAudioEngine::AUDIO_TYPE_UI)
        {
            // this shouldn't happen for now, as UI is forbidden in the log
            type_column["value"] = "UI";
        }
        else
        {
            std::string type;
            std::string icon;
            if(is_avatar)
            {
                type = "Avatar";
                icon = "inv_item_gesture.tga";
            }
            else
            {
                if(item.mIsTrigger)
                {
                    type = "llTriggerSound";
                    icon = "inv_item_sound.tga";
                }
                else
                {
                    if(item.mIsLooped)
                        type = "llLoopSound";
                    else
                        type = "llPlaySound";
                    icon = "inv_item_object.tga";
                }
            }

            type_column["value"] = icon;
            type_column["tool_tip"] = type;
        }

        LLSD& owner_column = element["columns"][2];
        owner_column["column"] = "owner";
        std::string fullname;
        BOOL is_group;
        if(gCacheName->getIfThere(item.mOwnerID, fullname, is_group))
        {
            if(is_group) fullname += " (Group)";
            owner_column["value"] = fullname;
        }
        else
            owner_column["value"] = item.mOwnerID.asString();

        LLSD& sound_column = element["columns"][3];
        sound_column["column"] = "sound";

        std::string uuid = item.mAssetID.asString();
        sound_column["value"] = uuid.substr(0, uuid.find_first_of("-")) + "...";

        list->addElement(element, ADD_BOTTOM);
    }

    list->selectMultiple(selected_ids);
    list->setScrollPos(scroll_pos);

    return FALSE;
}
// static
BOOL LLFloaterExploreSounds::tick()
{
	//if(childGetValue("pause_chk").asBoolean()) return FALSE;

	bool show_collision_sounds = childGetValue("collision_chk").asBoolean();
	bool show_repeated_assets = childGetValue("repeated_asset_chk").asBoolean();
	bool show_avatars = childGetValue("avatars_chk").asBoolean();
	bool show_objects = childGetValue("objects_chk").asBoolean();

	std::list<LLSoundHistoryItem> history;
	if(childGetValue("pause_chk").asBoolean())
	{
		history = mLastHistory;
	}
	else
	{
		std::map<LLUUID, LLSoundHistoryItem>::iterator map_iter = gSoundHistory.begin();
		std::map<LLUUID, LLSoundHistoryItem>::iterator map_end = gSoundHistory.end();
		for( ; map_iter != map_end; ++map_iter)
		{
			history.push_back((*map_iter).second);
		}
		LLSoundHistoryItemCompare c;
		history.sort(c);
		mLastHistory = history;
	}

	LLScrollListCtrl* list = getChild<LLScrollListCtrl>("sound_list");

	// Save scroll pos and selection so they can be restored
	S32 scroll_pos = list->getScrollPos();
	LLDynamicArray<LLUUID> selected_ids;
	std::vector<LLScrollListItem*> selected_items = list->getAllSelected();
	std::vector<LLScrollListItem*>::iterator selection_iter = selected_items.begin();
	std::vector<LLScrollListItem*>::iterator selection_end = selected_items.end();
	for(; selection_iter != selection_end; ++selection_iter)
		selected_ids.push_back((*selection_iter)->getUUID());

	list->clearRows();

	std::list<LLUUID> unique_asset_list;

	std::list<LLSoundHistoryItem>::iterator iter = history.begin();
	std::list<LLSoundHistoryItem>::iterator end = history.end();
	for( ; iter != end; ++iter)
	{
		LLSoundHistoryItem item = (*iter);

		bool is_avatar = item.mOwnerID == item.mSourceID;
		if(is_avatar && !show_avatars) continue;

		bool is_object = !is_avatar;
		if(is_object && !show_objects) continue;

		bool is_repeated_asset = std::find(unique_asset_list.begin(), unique_asset_list.end(), item.mAssetID) != unique_asset_list.end();
		if(is_repeated_asset && !show_repeated_assets) continue;

		if(!item.mReviewed)
		{
			item.mReviewedCollision	= std::find(&collision_sounds[0], &collision_sounds[num_collision_sounds], item.mAssetID) != &collision_sounds[num_collision_sounds];
			item.mReviewed = true;
		}
		bool is_collision_sound = item.mReviewedCollision;
		if(is_collision_sound && !show_collision_sounds) continue;

		unique_asset_list.push_back(item.mAssetID);

		LLSD element;
		element["id"] = item.mID;

		LLSD& playing_column = element["columns"][0];
		playing_column["column"] = "playing";
		if(item.mPlaying)
			playing_column["value"] = " Playing";
		else
			playing_column["value"] = llformat("%.1f min ago", (LLTimer::getElapsedSeconds() - item.mTimeStopped) / 60.f);

		LLSD& type_column = element["columns"][1];
		type_column["column"] = "type";
		if(item.mType == LLAudioEngine::AUDIO_TYPE_UI)
		{
			// this shouldn't happen for now, as UI is forbidden in the log
			type_column["value"] = "UI";
		}
		else
		{
			std::string type;

			if(is_avatar)
			{
				type = "Avatar";
			}
			else
			{
				if(item.mIsTrigger)
				{
					type = "llTriggerSound";
				}
				else
				{
					if(item.mIsLooped)
						type = "llLoopSound";
					else
						type = "llPlaySound";
				}
			}

			type_column["value"] = type;
		}

		LLSD& owner_column = element["columns"][2];
		owner_column["column"] = "owner";
		std::string fullname;
		BOOL is_group;
		if(gCacheName->getIfThere(item.mOwnerID, fullname, is_group))
		{
			if(is_group) fullname += " (Group)";
			owner_column["value"] = fullname;
		}
		else
			owner_column["value"] = item.mOwnerID.asString();

		LLSD& sound_column = element["columns"][3];
		sound_column["column"] = "sound";

		if (item.mOwnerID == gAgent.getID())
			sound_column["value"] = item.mAssetID.asString();
		else
			sound_column["value"] = LLUUID::null.asString();

		list->addElement(element, ADD_BOTTOM);
	}

	list->selectMultiple(selected_ids);
	list->setScrollPos(scroll_pos);

	return FALSE;
}
void LLFloaterMessageLog::conditionalLog(LogPayload entry)
{	
	if(!mMessageLogFilterApply)
		childSetText("log_status_text", llformat("Showing %d messages of %d", mFloaterMessageLogItems.size(), mMessagesLogged));

	FloaterMessageItem item = new LLEasyMessageLogEntry(entry, mEasyMessageReader);


	std::set<std::string>::const_iterator end_msg_name = item->mNames.end();
	std::set<std::string>::iterator iter_msg_name = item->mNames.begin();

	bool have_positive = false;

	for(; iter_msg_name != end_msg_name; ++iter_msg_name)
	{
		std::string find_name = *iter_msg_name;
		LLStringUtil::toLower(find_name);

		//keep the message if we allowed its name so long as one of its other names hasn't been blacklisted
		if(!have_positive && !mMessageLogFilter.mPositiveNames.empty())
		{
			if(std::find(mMessageLogFilter.mPositiveNames.begin(), mMessageLogFilter.mPositiveNames.end(), find_name) != mMessageLogFilter.mPositiveNames.end())
				have_positive = true;
		}
		if(!mMessageLogFilter.mNegativeNames.empty())
		{
			if(std::find(mMessageLogFilter.mNegativeNames.begin(), mMessageLogFilter.mNegativeNames.end(), find_name) != mMessageLogFilter.mNegativeNames.end())
			{
				delete item;
			return;
			}
		}
		//we don't have any negative filters and we have a positive match
		else if(have_positive)
			break;
	}

	//we had a positive filter but no positive matches
	if(!mMessageLogFilter.mPositiveNames.empty() && !have_positive)
	{
		delete item;
		return;
	}

	mFloaterMessageLogItems.push_back(item); // moved from beginning...

	if(item->mType == LLEasyMessageLogEntry::HTTP_REQUEST)
	{
		mIncompleteHTTPConvos.insert(HTTPConvoMap::value_type(item->mRequestID, item));
	}

	std::string net_name("\?\?\?");
	BOOL outgoing = item->isOutgoing();
	switch(item->mType)
	{
	case LLEasyMessageLogEntry::TEMPLATE:
		{
			LLHost find_host = outgoing ? item->mToHost : item->mFromHost;
			net_name = find_host.getIPandPort();
			std::list<LLNetListItem*>::iterator end = sNetListItems.end();
			for(std::list<LLNetListItem*>::iterator iter = sNetListItems.begin(); iter != end; ++iter)
			{
				if((*iter)->mCircuitData->getHost() == find_host)
				{
					net_name = (*iter)->mName;
					break;
				}
			}
		}
		break;
	case LLEasyMessageLogEntry::HTTP_REQUEST:
		{
			std::string url = get_base_url(item->mURL);
			std::list<LLNetListItem*>::iterator end = sNetListItems.end();
			for(std::list<LLNetListItem*>::iterator iter = sNetListItems.begin(); iter != end; ++iter)
			{
				LLViewerRegion* regionp = LLWorld::getInstance()->getRegionFromHandle((*iter)->mHandle); //TODO: Find a better way to do this.
				if(regionp && regionp->getCapURLNames(url).size())
				{
					net_name = (*iter)->mName;
					break;
				}
			}
		}
		break;
	default:
		break;
	}
	//add the message to the messagelog scroller
	LLSD element;
	element["id"] = item->mID;
	LLSD& sequence_column = element["columns"][0];
	sequence_column["column"] = "sequence";
	sequence_column["value"] = llformat("%u", item->mSequenceID);

	LLSD& type_column = element["columns"][1];
	type_column["column"] = "type";
	switch(item->mType)
	{
	case LLEasyMessageLogEntry::TEMPLATE:
		type_column["value"] = "UDP";
		break;
	case LLEasyMessageLogEntry::HTTP_REQUEST:
		type_column["value"] = "HTTP";
		break;
	default:
		type_column["value"] = "\?\?\?";
	}

	LLSD& direction_column = element["columns"][2];
	direction_column["column"] = "direction";
	if(item->mType == LLEasyMessageLogEntry::TEMPLATE)
		direction_column["value"] = outgoing ? "to" : "from";
	else if(item->mType == LLEasyMessageLogEntry::HTTP_REQUEST)
		direction_column["value"] = "both";

	LLSD& net_column = element["columns"][3];
	net_column["column"] = "net";
	net_column["value"] = net_name;

	LLSD& name_column = element["columns"][4];
	name_column["column"] = "name";
	name_column["value"] = item->getName();

	LLSD& summary_column = element["columns"][5];
	summary_column["column"] = "summary";
	summary_column["value"] = item->mSummary;
	LLScrollListCtrl* scrollp = getChild<LLScrollListCtrl>("message_log");

	S32 scroll_pos = scrollp->getScrollPos();
	scrollp->addElement(element, ADD_BOTTOM);

	if(scroll_pos > scrollp->getItemCount() - scrollp->getPageLines() - 4)
		scrollp->setScrollPos(scrollp->getItemCount());
}