/***************************************************************************
 *   Copyright (C) 2007 by Anistratov Oleg                                 *
 *   ower@users.sourceforge.net                                            *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License version 2        *
 *   as published by the Free Software Foundation;                         *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 ***************************************************************************/

#include "userslist.h"

#include <assert.h>

#include <QHostAddress>

#include "userinfo.h"
#include "userwgt.h"

UsersList::UsersList() :
  m_users            (NULL),
  m_usersNum         (0),
  m_maxUsersNum      (1024),
  m_hiddenUsers      (NULL),
  m_hiddenUsersNum   (0),
  m_maxHiddenUsersNum(1024)
{
  m_users = (UserWgt**)malloc(m_maxUsersNum * sizeof(UserWgt*));
  assert(NULL != m_users);

  m_hiddenUsers = (UserWgt**)malloc(m_maxHiddenUsersNum * sizeof(UserWgt*));
  assert(NULL != m_hiddenUsers);
}
//\*****************************************************************************
UsersList::~UsersList()
{
  qDebug("[~UsersList]\n");
  free(m_users);
  free(m_hiddenUsers);
}
//\*****************************************************************************
void UsersList::addUser(UserWgt* user)
{
  if(exists(user->info()->uid()))
    return;

  qDebug("[UsersList::addUser] uid = %s\n", QHostAddress(user->info()->ip()).toString().toAscii().data());

  if(++m_usersNum >= m_maxUsersNum)
  {
    m_maxUsersNum += 1024;
    m_users = (UserWgt**)realloc(m_users, m_maxUsersNum * sizeof(UserWgt*));
    assert(NULL != m_users);
  }

  m_users[m_usersNum - 1] = user;
}
//\*****************************************************************************
UserWgt* UsersList::findUser(quint64 uid) const
{
  for(uint i = 0; i < m_usersNum; i++)
    if(m_users[i]->info()->uid() == uid)
      return m_users[i];

  return NULL;
}

UserWgt* UsersList::findHidden(quint64 uid) const
{
  for(uint i = 0; i < m_hiddenUsersNum; i++)
    if(m_users[i]->info()->uid() == uid)
      return m_hiddenUsers[i];

  return NULL;
}

qint32 UsersList::findNum(quint64 uid) const
{
  for(uint i = 0; i < m_usersNum; i++)
    if(m_users[i]->info()->uid() == uid)
      return i;

  return -1;
}
//\*****************************************************************************
UserWgt* UsersList::enable(quint64 uid)
{
  uint num;

  for(num = 0; num < m_hiddenUsersNum; num++)
    if(m_hiddenUsers[num]->info()->uid() == uid)
      break;

  if(num >= m_hiddenUsersNum)
  {
    for(num = 0; num < m_usersNum; num++)
      if(m_users[num]->info()->uid() == uid)
        break;

    if(num >= m_usersNum)
      return NULL;
    else
      return m_users[num];
  }


  if(++m_usersNum >= m_maxUsersNum)
  {
    m_maxUsersNum += 1024;
    m_users = (UserWgt**)realloc(m_users, m_maxUsersNum * sizeof(UserWgt*));
    assert(NULL != m_users);
  }

  m_users[m_usersNum - 1] = m_hiddenUsers[num];
  m_hiddenUsers[num]->info()->setEnabled(true);
  m_hiddenUsers[num] = m_hiddenUsers[--m_hiddenUsersNum];

  return m_users[m_usersNum - 1];
}
//\*****************************************************************************
UserWgt* UsersList::disable(quint64 uid)
{
  int num = findNum(uid);

  if(num < 0)
    return NULL;

  if(++m_hiddenUsersNum >= m_maxHiddenUsersNum)
  {
    m_maxHiddenUsersNum += 1024;
    m_hiddenUsers = (UserWgt**)realloc(m_hiddenUsers, m_maxHiddenUsersNum * sizeof(UserWgt*));
    assert(NULL != m_hiddenUsers);
  }

  m_hiddenUsers[m_hiddenUsersNum - 1] = m_users[num];
  m_users[num]->info()->setEnabled(false);
  m_users[num] = m_users[--m_usersNum];

  return m_hiddenUsers[m_hiddenUsersNum - 1];
}
//\*****************************************************************************
void UsersList::disableAll()
{
  qDebug("[UsersList::disableAll]");
  uint i, j;

  for(i = 0; i < m_usersNum; i++)
    m_users[i]->info()->setEnabled(false);

  i = m_hiddenUsersNum;
  m_hiddenUsersNum += m_usersNum;
  if(m_hiddenUsersNum >= m_maxHiddenUsersNum)
  {
    m_maxHiddenUsersNum += 1024;
    m_hiddenUsers = (UserWgt**)realloc(m_hiddenUsers, m_maxHiddenUsersNum * sizeof(UserWgt*));
    assert(NULL != m_hiddenUsers);
  }

  for(j = 0; i < m_hiddenUsersNum && j < m_usersNum; i++, j++)
    m_hiddenUsers[i] = m_users[j];

  m_usersNum = 0;
}
//\*****************************************************************************
void UsersList::enableAll()
{
  qDebug("[UsersList::enableAll]");
  uint i, j;

  i = m_usersNum;
  m_usersNum += m_hiddenUsersNum;
  if(m_usersNum >= m_maxUsersNum)
  {
    m_maxUsersNum += 1024;
    m_users = (UserWgt**)realloc(m_users, m_maxUsersNum * sizeof(UserWgt*));
    assert(NULL != m_users);
  }

  for(j = 0; j < m_hiddenUsersNum && i < m_usersNum; i++, j++)
    m_users[i] = m_hiddenUsers[j];

  m_hiddenUsersNum = 0;

  for(i = 0; i < m_usersNum; i++)
    m_users[i]->info()->setEnabled(true);
}
//\*****************************************************************************
bool UsersList::enabled(quint64 uid) const
{
  UserWgt* usr = findUser(uid);

  return (usr && usr->info()->enabled());
}
//\*****************************************************************************
bool UsersList::exists(quint64 uid) const
{
  for(uint i = 0; i < m_usersNum; i++)
    if(m_users[i]->info()->uid() == uid)
      return true;

  for(uint i = 0; i < m_hiddenUsersNum; i++)
    if(m_hiddenUsers[i]->info()->uid() == uid)
      return true;

  return false;
}
//\*****************************************************************************
UserWgt* UsersList::user(int n) const
{
  Q_ASSERT(n >= 0);

  if(n < (int)m_usersNum)
    return m_users[n];

  return NULL;
}

UserWgt* UsersList::enableIfExists(quint64 uid)
{
  uint i;

  for(i = 0; i < m_hiddenUsersNum; i++)
    if(m_hiddenUsers[i]->info()->uid() == uid)
      return enable(uid);

  for(i = 0; i < m_usersNum; i++)
    if(m_users[i]->info()->uid() == uid)
      return enable(uid);

  return NULL;
}
