bool AbiCollabSessionManager::addAccount(AccountHandler* pHandler)
{
	UT_return_val_if_fail(pHandler, false);
	bool bUnique = true;
	for (UT_uint32 i = 0; i < m_vecAccounts.size() && bUnique; i++)
	{
		UT_continue_if_fail(m_vecAccounts[i]);
		if (pHandler->getStorageType() == m_vecAccounts[i]->getStorageType())
		{
			// Accounts are of same backend - compare if equal
			bUnique = !((*pHandler) == (*m_vecAccounts[i]));
		}
	}
	
	if (bUnique)
	{
		m_vecAccounts.push_back(pHandler);
	}
	else
	{
		_deleteAccount(pHandler);
		UT_DEBUGMSG(("User attempted to add duplicate account - request ignored.\n"));
	}
	
	return bUnique;
}
void AP_UnixDialog_CollaborationAccounts::eventDelete()
{
	UT_DEBUGMSG(("AP_UnixDialog_CollaborationAccounts::eventDelete()\n"));
	AccountHandler* pHandler = _getSelectedAccountHandler();
	UT_return_if_fail(pHandler);

	// TODO: we should ask for confirmation, as this account handler
	//		 could be in use by serveral AbiCollab Sessions
	UT_DEBUGMSG(("Delete account: %s of type %s\n",
			pHandler->getDescription().utf8_str(),
			pHandler->getDisplayType().utf8_str()
		));

	_deleteAccount(pHandler);

	// for now, recreate the whole model; but we should really just delete
	// the iter we got above
	_setModel(_constructModel());
}
bool AbiCollabSessionManager::destroyAccount(AccountHandler* pHandler)
{
	UT_return_val_if_fail(pHandler, false);

	for (UT_uint32 i = 0; i < m_vecAccounts.size(); i++)
	{
		UT_continue_if_fail(m_vecAccounts[i]);
		
		if (pHandler == m_vecAccounts[i])
		{
			UT_DEBUGMSG(("Destroying account handler %s\n", pHandler->getDescription().utf8_str()));

			// TODO: if a number of buddies are connected, then we should ask for confirmation
			
			// drop all buddies that belong to the account that is being deleted
			// from all active sessions
			for (UT_sint32 j = 0; j < m_vecSessions.getItemCount(); j++)
			{
				AbiCollab* pSession = m_vecSessions.getNthItem(j); 
				UT_continue_if_fail(pSession);
				
				// There can only be buddies from 1 account in an active session these days/
				// That means that if this session's account is the account we are destroying,
				// then we can kill off the entire session. Do nothing otherwise.
				if (pSession->getAclAccount() == pHandler)
				{
					UT_DEBUGMSG(("Session %s is running on this account, destroying it!\n", pSession->getSessionId().utf8_str()));
					destroySession(pSession);
				}
			}

			m_vecAccounts.erase(m_vecAccounts.begin() + i, m_vecAccounts.begin() + i + 1);
			_deleteAccount(pHandler);
			return true;
		}
	}
	return false;
}
void AbiCollabSessionManager::loadProfile()
{
	UT_DEBUGMSG(("AbiCollabSessionManager::loadProfile()\n"));

	gchar *s = g_build_filename(XAP_App::getApp()->getUserPrivateDirectory(), 
								"AbiCollab.Profile", (void*)0);
	UT_UTF8String profile(s);
	FREEP(s);

	GsfInput* in = NULL;
	char *uri = UT_go_filename_to_uri(profile.utf8_str());
	UT_return_if_fail(uri);

	in = UT_go_file_open(uri, NULL); // TODO: shouldn't use NULL here, but check for errors
	FREEP(uri);
	if (!in)
		return;

	guint8 const* contents = gsf_input_read(in, gsf_input_size(in), NULL);
	if (contents)
	{
		xmlDocPtr reader = xmlReadMemory(reinterpret_cast<const char*>(contents), 
							strlen(reinterpret_cast<const char*>(contents)), 0, "UTF-8", 0);
		if (reader)
		{
			xmlNode* node = xmlDocGetRootElement(reader);
			if (node)
			{
				if (strcmp(reinterpret_cast<const char*>(node->name), "AbiCollabProfile") == 0)
				{
					for (xmlNode* accountNode = node->children; accountNode; accountNode = accountNode->next)
					{
						// TODO: check if this node is really an AccountHandler node

						// find the account handler belonging to this type
						xmlChar* prop = xmlGetProp(accountNode, BAD_CAST "type");
						UT_UTF8String handlerType = reinterpret_cast<char *>(prop); 
						xmlFree(prop);
						std::map<UT_UTF8String, AccountHandlerConstructor>::iterator handler_iter = m_regAccountHandlers.find(handlerType);
						if (handler_iter == m_regAccountHandlers.end())
						    continue; // could happen for example when the sugar backend is found in the profile, which does not have a registered account handler belowing to it for now
						
						AccountHandlerConstructor constructor = handler_iter->second;
						AccountHandler* pHandler = constructor();
						UT_continue_if_fail(pHandler);

						for (xmlNode* accountProp = accountNode->children; accountProp; accountProp = accountProp->next)
						{
							if (accountProp->type == XML_ELEMENT_NODE)
							{
								// some node names are pre-defined...
								if (strcmp(reinterpret_cast<const char*>(accountProp->name), "buddies") == 0)
								{
									for (xmlNode* buddyNode = accountProp->children; buddyNode; buddyNode = buddyNode->next)
									{
										if (buddyNode->type != XML_ELEMENT_NODE)
										    continue;
										UT_continue_if_fail(strcmp(reinterpret_cast<const char*>(buddyNode->name), "buddy") == 0);
										UT_continue_if_fail(buddyNode->children);
										
										// read all buddy properties
										PropertyMap vBuddyProps;
										for (xmlNode* buddyPropertyNode = buddyNode->children; buddyPropertyNode; buddyPropertyNode = buddyPropertyNode->next)
										{
											UT_continue_if_fail(buddyPropertyNode->type == XML_ELEMENT_NODE);
											
											UT_UTF8String buddyPropValue = reinterpret_cast<const char*>(xmlNodeGetContent(buddyPropertyNode));
											UT_continue_if_fail(buddyPropertyNode->name && *buddyPropertyNode->name && buddyPropValue.size() > 0);
											
											vBuddyProps.insert(PropertyMap::value_type(
													reinterpret_cast<const char*>(buddyPropertyNode->name), 
													buddyPropValue.utf8_str())
												);
										}
										
										// construct the buddy	
										BuddyPtr pBuddy = pHandler->constructBuddy(vBuddyProps);
										if (pBuddy)
										{
											// add the buddy to the account handler
											pHandler->addBuddy(pBuddy);
										}
									}
								}
								else
								{
									// ... the rest are generic properties
									UT_UTF8String propValue = reinterpret_cast<const char*>(xmlNodeGetContent(accountProp));
									pHandler->addProperty(reinterpret_cast<const char*>(accountProp->name), propValue.utf8_str());
								}
							}
						}

						// add the account to the account list if it is not a duplicate
						if (addAccount(pHandler))
						{
							if (pHandler->autoConnect())
								pHandler->connect();
						}
						else
						{
							_deleteAccount(pHandler);
						}
					}
				}
			}
			xmlFreeDoc(reader);
		}
	}
	g_object_unref(G_OBJECT(in));
}
void AbiCollabSessionManager::destroyAccounts(void)
{
	for (UT_uint32 i = 0; i < m_vecAccounts.size(); i++)
		_deleteAccount(m_vecAccounts[i]);
	m_vecAccounts.clear();
}