// Userlist.C  -*- C++ -*-
// Copyright (c) 1997, 1998 Etienne BERNARD
// Copyright (C) 2002 Clinton Ebadi

// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// any later version.

// 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.

// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.

#include <fstream>
#include <iostream>

#include "UserList.H"
#include "StringTokenizer.H"

UserList::UserList(String filename)
  : listFilename(filename)
{
  read();
}

UserList::~UserList()
{
  clear();
}

void
UserList::read()
{
  std::ifstream file(listFilename);
  String temp, empty = "";
  int line = 1;

  clear();

  if (!file) {
    std::cerr << "I cannot find the file " << listFilename << std::endl;
    return;
  }

  while (file >> temp, temp.length() != 0) {
    StringTokenizer st(temp);
    if (st.countTokens(':') != 7) {
      std::cerr << "Error when reading userlist (" << listFilename <<
        ") line " << line << "...\n";
      return;
    }
    String mask = st.nextToken(':');
    String maskChannel = st.nextToken(':');
    String level = st.nextToken(':');
    String prot = st.nextToken(':');
    String aop = st.nextToken(':');
    String expiration = st.nextToken(':');
    String password = st.rest().trim();
    if (password == "*NONE*")
      password = "";
    l.push_back(new UserListItem(mask, maskChannel, atoi(level),
                                 atoi(prot), atoi(aop),
                                 atol(expiration), password));
    line++;
  }
  file.close();
}

void
UserList::save()
{
  std::list<UserListItem *>::iterator it = l.begin();
  std::ofstream file(listFilename);
  
  if (!file)
    return;

  ++it; // We skip the bot's entry
  for ( ; it != l.end(); ++it)
    if ((*it)->isStillValid()) {
      file << (*it)->mask.getMask() << ":"
           << (*it)->channelMask.getMask() << ":"
           << (*it)->level << ":"
           << (*it)->prot << ":"
           << (*it)->aop << ":"
           << (*it)->expirationDate << ":";
      if ((*it)->passwd == "")
        file << "*NONE*";
      else
        file << (*it)->passwd;
      file << std::endl;
    }
}

void
UserList::clear()
{
  UserListItem *uli;

  while (!l.empty()) {
    uli = (*l.begin());
    l.erase(l.begin());
    delete uli;
  }
}

void
UserList::addUser(String m, String mc, int lev, int p, bool a,
                  std::time_t e, String pa)
{
  l.push_back (new UserListItem(m, mc, lev, p, a, e, pa));
}

void
UserList::addUserFirst(String m, String mc, int lev, int p,
                       bool a, std::time_t e, String pa)
{
  l.push_front (new UserListItem(m, mc, lev, p, a, e, pa, true));
}

UserListItem *
UserList::getUserListItem(String nuh, String channel)
{
  for (std::list<UserListItem *>::iterator it = l.begin();
       it != l.end(); ++it)
    if ((*it)->matches(nuh, channel)) {
      return (*it);
    }
  
  return 0;
}

int
UserList::getMaxLevel(String nuh)
{
  int level = -1;
  std::time_t current_time = std::time (0);

  for (std::list<UserListItem *>::iterator it = l.begin();
       it != l.end(); it++)
    if ((*it)->matches(nuh) && level < (*it)->level &&
        ((*it)->expirationDate == -1 ||
         (*it)->expirationDate > current_time) &&
        ((*it)->passwd == "" || (*it)->identified > 0))
      level = (*it)->level;

  return level;
}

int
UserList::getLevel(String nuh, String channel)
{
  if (UserListItem *uli = getUserListItem(nuh, channel))
    return uli->level;

  return -1;
}

int
UserList::getMaxProt(String nuh, String channel)
{
  int prot = -1;
  std::time_t current_time = std::time (0);

  for (std::list<UserListItem *>::iterator it = l.begin();
       it != l.end(); it++) {
    Mask m(nuh), mc(channel), msc((*it)->channelMask.getMask());
    if (m.matches((*it)->mask) &&
        (mc.matches((*it)->channelMask) || msc.matches(channel)) &&
        prot < (*it)->prot &&
        ((*it)->expirationDate == -1 ||
         (*it)->expirationDate > current_time)) {
      prot = (*it)->prot;
    }
  }
  return prot;
}

bool
UserList::isInUserList(String nuh, String maskChannel)
{
  for (std::list<UserListItem *>::iterator it = l.begin();
       it != l.end();
       ++it)
    if ((*it)->matches(nuh, maskChannel))
      return true;
  
  return false;
}

void
UserList::removeFirst()
{
  UserListItem * uli = *(l.begin());
  if (uli->autoEntry) {
    l.erase(l.begin());
    delete uli;
  };
}

void
UserList::removeUser(String mask, String maskChannel)
{
  for (std::list<UserListItem *>::iterator it = l.begin();
       it != l.end();
       ++it)
    if ((*it)->mask.getMask() == mask &&
        (*it)->channelMask.getMask() == maskChannel) {
      delete (*it);
      l.erase(it);
      return;
    }
}


syntax highlighted by Code2HTML, v. 0.9.1