/***************************************************************************
                          usertabimpl.cpp  -  description
                             -------------------
    begin                : Mon Jul 15 2002
    copyright            : (C) 2002 by Jan Sch�er
    email                : janschaefer@users.sourceforge.net
 ***************************************************************************/

/******************************************************************************
 *                                                                            *
 *  This file is part of KSambaPlugin.                                        *
 *                                                                            *
 *  KSambaPlugin 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         *
 *  (at your option) any later version.                                       *
 *                                                                            *
 *  KSambaPlugin 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 KSambaPlugin; if not, write to the Free Software                     *
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA  *
 *                                                                            *
 ******************************************************************************/

#include <unistd.h> // for getuid

#include <tqcombobox.h>
#include <tqstringlist.h>
#include <passwd.h>
#include <tqregexp.h>
#include <tqtable.h>
#include <tqcheckbox.h>
#include <tqpushbutton.h>
#include <tqlineedit.h>

#include <klistview.h>
#include <klocale.h>
#include <kdebug.h>
#include <kiconloader.h>
#include <kinputdialog.h>

#include "usertabimpl.h"
#include "sambashare.h"
#include "smbpasswdfile.h"
#include "passwd.h"
#include "groupselectdlg.h"
#include "userselectdlg.h"
#include "expertuserdlg.h"

#include <assert.h>

/**
 * @pre share is not null
 * @post _share = share
 */
UserTabImpl::UserTabImpl(TQWidget* parent, SambaShare* share)
  : UserTab(parent)
{
  if (share == 0L) {
    kdWarning() << "WARNING: UserTabImpl constructor: share parameter is null!" << endl;
    return;
  }

  _share = share;
  userTable->setLeftMargin(0);
 // userTable->setColumnStretchable ( 3, true );

}

UserTabImpl::~UserTabImpl()
{
}

void UserTabImpl::load()
{
  if (_share == 0L)
    return;

  loadForceCombos();
  loadUsers(_share->getValue("valid users"),
            _share->getValue("read list"),
            _share->getValue("write list"),
            _share->getValue("admin users"),
            _share->getValue("invalid users"));
}

void UserTabImpl::loadUsers(const TQString & validUsersStr,
                            const TQString & readListStr,
                            const TQString & writeListStr,
                            const TQString & adminUsersStr,
                            const TQString & invalidUsersStr)
{
  userTable->setNumRows(0);
  TQStringList validUsers = TQStringList::split(TQRegExp("[,\\s]+"),validUsersStr);
  TQStringList readList = TQStringList::split(TQRegExp("[,\\s]+"),readListStr);
  TQStringList writeList = TQStringList::split(TQRegExp("[,\\s]+"),writeListStr);
  TQStringList adminUsers = TQStringList::split(TQRegExp("[,\\s]+"),adminUsersStr);
  TQStringList invalidUsers = TQStringList::split(TQRegExp("[,\\s]+"),invalidUsersStr);

  // if the valid users list contains no entries
  // then all users are allowed, except those that are
  // in the invalid list
  if (validUsers.empty())
    allUnspecifiedUsersCombo->setCurrentItem(0);
  else
    allUnspecifiedUsersCombo->setCurrentItem(1);

  removeDuplicates(validUsers,readList,writeList,adminUsers,invalidUsers);

  addListToUserTable(adminUsers,3);
  addListToUserTable(writeList,2);
  addListToUserTable(readList,1);
  addListToUserTable(validUsers,0);
  addListToUserTable(invalidUsers,4);

}


void UserTabImpl::loadForceCombos() {
  forceUserCombo->insertItem("");
  forceGroupCombo->insertItem("");

  TQStringList unixGroups = getUnixGroups();

  forceUserCombo->insertStringList( getUnixUsers() );
  forceGroupCombo->insertStringList( unixGroups );

  setComboToString(forceUserCombo, _share->getValue("force user"));
  setComboToString(forceGroupCombo, _share->getValue("force group"));
}

/**
 * Remove all duplicates of the different list, so that
 * all lists are disjunct.
 */
void UserTabImpl::removeDuplicates( TQStringList & validUsers, TQStringList & readList,
                       TQStringList & writeList, TQStringList & adminUsers,
                       TQStringList & invalidUsers)
{
  removeAll(adminUsers, writeList);

  removeAll(writeList, readList);
  removeAll(adminUsers, readList);

  removeAll(readList, validUsers);
  removeAll(writeList, validUsers);
  removeAll(adminUsers, validUsers);

  removeAll(invalidUsers, validUsers);
  removeAll(invalidUsers, readList);
  removeAll(invalidUsers, writeList);
  removeAll(invalidUsers, adminUsers);
}

/**
 * Remove all entries of entryList from the fromList
 */
void UserTabImpl::removeAll(TQStringList & entryList, TQStringList & fromList) {
  for (TQStringList::Iterator it = entryList.begin(); it != entryList.end(); ++it) {
    fromList.remove((*it));
  }
}


void UserTabImpl::addListToUserTable(const TQStringList & list, int accessRight) {

  for (TQStringList::ConstIterator it = list.begin(); it != list.end(); ++it) {
    addUserToUserTable(*it,accessRight);
  }
}

void UserTabImpl::addUserToUserTable(const TQString & user, int accessRight) {
    int row = userTable->numRows();
    userTable->setNumRows(row+1);
    setAllowedUser(row, user);

    TQComboTableItem* comboItem = static_cast<TQComboTableItem*>(userTable->item(row,3));
    comboItem->setCurrentItem(accessRight);
}

TQString UserTabImpl::removeQuotationMarks(const TQString & name) {
    TQString result = name;
    if (name.left(1) == "\"") {
        result = result.left(result.length()-1);
        result = result.right(result.length()-1);
    }
    return result;
}

TQString UserTabImpl::removeGroupTag(const TQString & name) {
  TQString result = name;


  if (nameIsGroup(result)) {
    result = result.right(result.length()-1);
    if (nameIsGroup(result))
      result = result.right(result.length()-1);
  }

  return result;
}


bool UserTabImpl::nameIsGroup(const TQString & name) {
  TQString quoteless = removeQuotationMarks(name);
  if (quoteless.left(1) == "@" ||
      quoteless.left(1) == "+" ||
      quoteless.left(1) == "&")
      return true;

  return false;

}

void UserTabImpl::setAllowedUser(int i, const TQString & name)
{
    TQStringList accessRights;
    accessRights << i18n("Default") << i18n("Read only") << i18n("Writeable") << i18n("Admin") << i18n("Reject");

    TQString uid;
    TQString gid;

    TQString name2 = name;

    if (nameIsGroup(name2))
    {
      TQString name3 = removeGroupTag(name2);
      uid = "";
      gid = TQString::number(getGroupGID(name3));
      _specifiedGroups << name3;
    }
    else
    {
      uid = TQString::number(getUserUID(name2));
      gid = TQString::number(getUserGID(name2));
      _specifiedUsers << name2;
    }

    if (name2.contains(' '))
        name2 = "\""+name2+"\"";


    TQTableItem* item = new TQTableItem( userTable,TQTableItem::Never, name2 );
    userTable->setItem(i,0,item);

    item = new TQTableItem( userTable,TQTableItem::Never, uid );
    userTable->setItem(i,1,item);

    item = new TQTableItem( userTable,TQTableItem::Never, gid );
    userTable->setItem(i,2,item);

    TQComboTableItem* comboItem = new TQComboTableItem( userTable,accessRights);
    userTable->setItem(i,3,comboItem);

}

void UserTabImpl::addUserBtnClicked()
{
  if (getuid() == 0) {
    UserSelectDlg *dlg = new UserSelectDlg();
    dlg->init(_specifiedUsers,_share);

    TQStringList selectedUsers = dlg->getSelectedUsers();

    if (dlg->exec()) {
        for (TQStringList::Iterator it = selectedUsers.begin(); it != selectedUsers.end(); ++it)
        {
            addUserToUserTable(*it,dlg->getAccess());
        }
    }

    delete dlg;
  } else {
    bool ok;
    TQString name = KInputDialog::getText(i18n("Add User"),i18n("Name:"),
                                         TQString::null,&ok );
                                         
    if (ok)                                         
        addUserToUserTable(name,0);
  }
}

void UserTabImpl::removeSelectedBtnClicked()
{
  TQMemArray<int>rows;

  int j=0;

  for (int i=0; i<userTable->numRows(); i++)
  {
    if (userTable->isRowSelected(i))
    {
      if (nameIsGroup(userTable->item(i,0)->text())) {
        _specifiedGroups.remove( removeGroupTag(removeQuotationMarks(userTable->item(i,0)->text())));
      } else
        _specifiedUsers.remove(userTable->item(i,0)->text());

      rows.resize(j+1);
      rows[j] = i;
      j++;
    }
  }

  userTable->removeRows(rows);
}


void UserTabImpl::addGroupBtnClicked()
{
  GroupSelectDlg *dlg = new GroupSelectDlg();
  dlg->init(_specifiedGroups);
  TQStringList selectedGroups = dlg->getSelectedGroups();
  if (dlg->exec()) {
    for (TQStringList::Iterator it = selectedGroups.begin(); it != selectedGroups.end(); ++it)
    {
        kdDebug(5009) << "GroupKind: " << dlg->getGroupKind() << endl;
        TQString name = dlg->getGroupKind() + (*it);
        addUserToUserTable(name,dlg->getAccess());
    }
  }

  delete dlg;
}

void UserTabImpl::expertBtnClicked() {
    ExpertUserDlg *dlg = new ExpertUserDlg();
    TQString validUsersStr;
    TQString readListStr;
    TQString writeListStr;
    TQString adminUsersStr;
    TQString invalidUsersStr;

    saveUsers(validUsersStr,readListStr,writeListStr,adminUsersStr,invalidUsersStr);

    dlg->validUsersEdit->setText(validUsersStr);
    dlg->readListEdit->setText(readListStr);
    dlg->writeListEdit->setText(writeListStr);
    dlg->adminUsersEdit->setText(adminUsersStr);
    dlg->invalidUsersEdit->setText(invalidUsersStr);

    if (dlg->exec()) {
        loadUsers(dlg->validUsersEdit->text(),
                  dlg->readListEdit->text(),
                  dlg->writeListEdit->text(),
                  dlg->adminUsersEdit->text(),
                  dlg->invalidUsersEdit->text());

    }

    delete dlg;
}

void UserTabImpl::save()
{
  TQString validUsersStr;
  TQString readListStr;
  TQString writeListStr;
  TQString adminUsersStr;
  TQString invalidUsersStr;

  saveUsers(validUsersStr,readListStr,writeListStr,adminUsersStr,invalidUsersStr);

  _share->setValue("valid users",validUsersStr);
  _share->setValue("read list", readListStr);
  _share->setValue("write list", writeListStr);
  _share->setValue("admin users", adminUsersStr);
  _share->setValue("invalid users", invalidUsersStr);

  _share->setValue("force user",forceUserCombo->currentText( ) );
  _share->setValue("force group",forceGroupCombo->currentText( ) );
}

void UserTabImpl::saveUsers(TQString & validUsersStr,
                            TQString & readListStr,
                            TQString & writeListStr,
                            TQString & adminUsersStr,
                            TQString & invalidUsersStr)
{
  TQStringList validUsers;
  TQStringList writeList;
  TQStringList readList;
  TQStringList adminUsers;
  TQStringList invalidUsers;

  bool allowAllUsers = allUnspecifiedUsersCombo->currentItem() == 0;

  for (int i=0; i<userTable->numRows(); i++)
  {
    TQTableItem* item = userTable->item(i,0);
    TQComboTableItem* comboItem = static_cast<TQComboTableItem*>(userTable->item(i,3));

    if (! allowAllUsers && comboItem->currentItem() < 4)
       validUsers.append(item->text());

    switch (comboItem->currentItem())
    {
      case 0 : break;
      case 1 : readList.append(item->text());break;
      case 2 : writeList.append(item->text());break;
      case 3 : adminUsers.append(item->text());break;
      case 4 : invalidUsers.append(item->text());break;
    }
  }

  validUsersStr = validUsers.join(",");
  readListStr = readList.join(",");
  writeListStr = writeList.join(",");
  adminUsersStr = adminUsers.join(",");
  invalidUsersStr = invalidUsers.join(",");
}



#include "usertabimpl.moc"