KviRegisteredUser * KviRegisteredUserDataBase::findUserWithMask(const KviIrcMask & mask)
{
	KviRegisteredUserMask * m = findExactMask(mask);
	if(m)
		return m->user();
	return nullptr;
}
KviRegisteredUser * KviRegisteredUserDataBase::findMatchingUser(const QString & nick, const QString & user, const QString & host)
{
	KviRegisteredUserMask * m = findMatchingMask(nick, user, host);
	if(m)
		return m->user();
	return nullptr; // no match at all
}
bool KviRegisteredUserDataBase::removeMask(const KviIrcMask &mask)
{
	// find the mask pointer
	KviRegisteredUserMask * m = findExactMask(mask);
	// and remove it
	if(m){
		if(removeMaskByPointer(m->mask()))
		{
			return true;
		}
	}
	return 0;
}
static void append_mask_to_list(KviRegisteredUserMaskList * l, KviRegisteredUser * u, KviIrcMask * mask)
{
	KviRegisteredUserMask * newMask = new KviRegisteredUserMask(u, mask);
	int idx = 0;
	for(KviRegisteredUserMask * m = l->first(); m; m = l->next())
	{
		if(m->nonWildChars() < newMask->nonWildChars())
		{
			l->insert(idx, newMask);
			return;
		}
		idx++;
	}
	l->append(newMask);
}
KviRegisteredUserMask * KviRegisteredUserDataBase::findExactMask(const KviIrcMask &mask)
{
	// first lookup the nickname in the maskDict
	if(mask.nick()=="") return 0;
	KviRegisteredUserMaskList * l = m_pMaskDict->find(mask.nick());
	if(l)
	{
		for(KviRegisteredUserMask *m = l->first();m;m = l->next())
		{
			if(*(m->mask()) == mask)return m;
		}
	}
	// not found....lookup the wild ones
	for(KviRegisteredUserMask * m = m_pWildMaskList->first();m;m = m_pWildMaskList->next())
	{
		if(*(m->mask()) == mask)return m;
	}
	return 0; // no match at all
}
KviRegisteredUserMask * KviRegisteredUserDataBase::findMatchingMask(const QString & nick,const QString &user,const QString & host)
{
	// first lookup the nickname in the maskDict
	if(nick.isEmpty()) return 0;
	KviRegisteredUserMaskList * l = m_pMaskDict->find(nick);
	if(l)
	{
		for(KviRegisteredUserMask *m = l->first();m;m = l->next())
		{
			if(m->mask()->matchesFixed(nick,user,host))return m;
		}
	}
	// not found....lookup the wild ones
	for(KviRegisteredUserMask * m = m_pWildMaskList->first();m;m = m_pWildMaskList->next())
	{
		if(m->mask()->matchesFixed(nick,user,host))return m;
	}
	return 0; // no match at all
}
bool KviRegisteredUserDataBase::removeMaskByPointer(KviIrcMask * mask)
{
	if(!mask)
		return 0;
	if(mask->hasWildNick())
	{
		// remove from the wild list
		for(KviRegisteredUserMask * m = m_pWildMaskList->first(); m; m = m_pWildMaskList->next())
		{
			if(m->mask() == mask)
			{
				// ok..got it, remove from the list and from the user struct (user struct deletes it!)
				emit(userChanged(mask->nick()));
				m->user()->removeMask(mask);   // this one deletes m->mask()
				m_pWildMaskList->removeRef(m); // this one deletes m
				return true;
			}
		}
		// not found ...opz :)
	}
	else
	{
		KviRegisteredUserMaskList * l = m_pMaskDict->find(mask->nick());
		if(l)
		{
			// FIXME: #warning "Here we could compare the host and username only: nick matches for sure"
			for(KviRegisteredUserMask * m = l->first(); m; m = l->next())
			{
				if(m->mask() == mask)
				{
					QString nick = mask->nick();
					emit(userChanged(nick));
					m->user()->removeMask(mask); // this one deletes m->mask() (or mask)
					l->removeRef(m);             // this one deletes m
					if(l->count() == 0)
						m_pMaskDict->remove(nick);
					return true;
				}
			}
			// not found ...opz
		}
	}
	// not found...
	return false;
}
KviRegisteredUser * KviRegisteredUserDataBase::addMask(KviRegisteredUser * u, KviIrcMask * mask)
{
	if(!u || !mask)
		return nullptr;
	KVI_ASSERT(u == m_pUserDict->find(u->name()));

	KviRegisteredUserMaskList * l;
	if(mask->hasWildNick())
	{
		for(KviRegisteredUserMask * m = m_pWildMaskList->first(); m; m = m_pWildMaskList->next())
		{
			if(*(m->mask()) == *mask)
			{
				delete mask;
				mask = nullptr;
				return m->user();
			}
		}
		// not found ...ok... add it
		// masks with more info go first in the list
		l = m_pWildMaskList;
	}
	else
	{
		l = m_pMaskDict->find(mask->nick());
		if(l)
		{
			// FIXME: #warning "Here we could compare the host and username only: nick matches for sure"
			for(KviRegisteredUserMask * m = l->first(); m; m = l->next())
			{
				if(*(m->mask()) == *mask)
				{
					delete mask;
					mask = nullptr;
					return m->user();
				}
			}
			// not found ...ok... add it
		}
		else
		{
			// not found ...ok... add it
			// this is the first mask in the list
			l = new KviRegisteredUserMaskList;
			l->setAutoDelete(true);
			if(!u->addMask(mask))
			{
				qDebug("Oops! Received an incoherent regusers action, recovered?");
				delete l;
				l = nullptr;
			}
			else
			{
				append_mask_to_list(l, u, mask);
				m_pMaskDict->insert(mask->nick(), l);
			}
			return nullptr;
		}
	}
	// Ok...add it
	if(!u->addMask(mask))
	{
		qDebug("Oops! Received an incoherent regusers action, recovered?");
		return nullptr; // ops...already there ?
	}
	append_mask_to_list(l, u, mask);
	return nullptr;
}