//
// C++ Implementation: c6roomlist
//
// Description:
//
//
// Author: Giorgio A. <openc6@hotmail.com>, (C) 2004
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include <qlistview.h>
#include <qpopupmenu.h>
#include <qpixmap.h>
#include <qiconset.h>
#include <qpushbutton.h>
#include <qcombobox.h>
#include <qlineedit.h>
#include <qlabel.h>
#include <qrect.h>
#include <qgroupbox.h>
#include <qmessagebox.h>
#include <qinputdialog.h>
#include <qradiobutton.h>
#include <qcheckbox.h>
#include <qpainter.h>
#include <qpalette.h>
#include <qtooltip.h>
#include <qheader.h>
#include <qtextedit.h>
#include "c6button.h"
#include <qfile.h>
#include <qlayout.h>
#include <qregexp.h>
#include <qapplication.h>
#include <qstring.h>
#include "c6roomlist.h"
#include "c6pixmapcache.h"
#include "c6settings.h"
#include "c6global.h"
#include "c6invitedialog.h"

enum ROOM_ACTION
{
    ROOM_ENTER,
    ROOM_PROFILE,
    ROOM_INVITE
};    

static const int MAX_ROOM_LEN = 35;
static const QString SEARCHWAITSTR = "Ricerca in corso.......";
static const QString NO_ROOM_FOUND_MSG = "Nessuna stanza trovata";
static const int MIN_TREE_POS_ID = 50;
static const int MAX_TREE_POS_ID = 58;    

class C6ListViewItem : public QListViewItem
{

public :
    C6ListViewItem(QListViewItem* root,QListViewItem* after,QListView * parent,QString const& label,int usersCount = -1) :
            QListViewItem(root,after),
            listview(parent)
    {
        setText(0,label);      
        if (usersCount != -1)    
        {         
            setText(1,"["+QString::number(usersCount)+"]");         
        }            
    };

    C6ListViewItem(QListView* parent,QListViewItem* after,QString const& label,int usersCount = -1) :
            QListViewItem(parent,after),
            listview(parent)   
    {
        setText(0,label);     
        if (usersCount != -1)    
        {         
            setText(1,"["+QString::number(usersCount)+"]");         
        }         
    };            

    bool isAlternate()
    {
        int count=0;
        QListViewItem *tmp;

        tmp = listview->firstChild();

        while (tmp)
        {
            if (tmp == this)
            {
                break;
            }
            count++;
            tmp = tmp->nextSibling();
        }

        return((count % 2) ? true : false);
    }

    void paintCell(QPainter *painter, const QColorGroup &cg,int column,
                   int width, int align)
    {
        painter->save();
        QColorGroup grp(cg);

        if (isAlternate())
        {
            grp.setColor(QColorGroup::Base,QColor(237,244,249));
        }

        QListViewItem::paintCell(painter, grp, column,width,align);
        painter->restore();
    }

private :
    QListView *listview;
};


C6RoomList::C6RoomList(std::vector<C6Proto::Category> const& category,QWidget *parent, const char *name): rooms(parent, name)
        ,_category(category) 
        ,_roomListMenu(0)                 
{
    C6Global &global = C6Global::getInstance();
    QString path = global.getSkinPath();

    setIcon(C6PixmapCache::getInstance().getPixmap(path+"icon16x16.png"));   
    
    exitButtonPlaceHolder->hide();
    C6Button *exitButton = new C6Button(frame15,0,0,path+"chat_71.png",
                                        path+"chat_over_109.png");
    layout22->addWidget(exitButton);
    connect(exitButton,SIGNAL(clicked()),this,SLOT(close()));
   
    enterRoomPlaceHolder->hide();
    C6Button *enterButton = new C6Button(frame87,0,0,path+"roomList_40.png",
                                         path+"roomList_over_40.png",
                                         path+"roomList_over_40.png");
    connect(enterButton,SIGNAL(clicked()),this,SLOT(enterRoom()));
    layout79_2->insertWidget(0,enterButton);    
    QToolTip::add
        (enterButton,"Entra nella stanza selezionata o specificata"); 
    
  
    searchRoomPlaceHolder->hide();
    C6Button *searchButton = new C6Button(frame87,0,0,path+"roomList_29.png",
                                          path+"roomList_over_29.png",
                                          path+"roomList_over_29.png");                              
    layout79_2->addWidget(searchButton);
    connect(searchButton,SIGNAL(clicked()),this,SLOT(searchRoom()));

    QToolTip::add
        (searchButton,"Ricerca la stanza selezionata nella categoria");      
   
    createPlaceHolder->hide();
    C6Button *createButton = new C6Button(frame53,0,0,path+"roomList_30.png",
                                          path+"roomList_over_30.png",
                                          path+"roomList_over_30.png");
    layout108->addWidget(createButton);
    connect(createButton,SIGNAL(clicked()),this,SLOT(createRoom()));
    QToolTip::add
            (createButton,"Crea la stanza specificata in Nome stanza");       

    QWidget *upParent = reinterpret_cast<QWidget*>(aboutButtonPlaceHolder->parent());
    C6Button* aboutButton = new C6Button(upParent,0,0,path+"chat_68.png",
                                         path+"chat_over_68.png",
                                         path+"chat_over_68.png");
    QToolTip::add
            (aboutButton,"Informazioni su OpenC6");
    aboutButtonPlaceHolder->hide();

    layout23->addWidget(aboutButton);   
    connect(aboutButton,SIGNAL(clicked()),this,SLOT(aboutClicked()));   
    
    _roomListMenu = new QPopupMenu(this);
    _roomListMenu->insertItem(QIconSet(QPixmap(path+"forward.png")),
                     "Entra",ROOM_ENTER);
   /* menu->insertItem(QIconSet(QPixmap(path+"login-photo32.png")),
    "Profilo",ROOM_PROFILE); */
    _roomListMenu->insertItem(QIconSet(QPixmap(path+"hotsync_busy.png")),
                     "Invita in chat",ROOM_INVITE);

   
    publicSwitch->setChecked(true);
    privateSwitch->setChecked(false);
    systemSwitch->setChecked(true); 
    userSwitch->setChecked(false);    
    
    connect(publicSwitch,SIGNAL(clicked()),this,SLOT(publicSwitchClicked()));
    connect(privateSwitch,SIGNAL(clicked()),this,SLOT(privateSwitchClicked()));
    connect(systemSwitch,SIGNAL(clicked()),this,SLOT(systemSwitchClicked()));
    connect(userSwitch,SIGNAL(clicked()),this,SLOT(userSwitchClicked()));
   
    connect(roomList,SIGNAL(doubleClicked (QListViewItem *)),this,
            SLOT(doubleClickList(QListViewItem*)));
    connect(roomList,SIGNAL(selectionChanged(QListViewItem*)),SLOT(roomSelectionChanged(QListViewItem*)));
    
    connect(roomList,SIGNAL(contextMenuRequested(QListViewItem *, const QPoint&,int)),
            this, SLOT(menuSelect(QListViewItem *, const QPoint &,int)));

    connect(roomList,SIGNAL(currentChanged(QListViewItem*)),this,
            SLOT(curItemSelected(QListViewItem *)));
            
    connect(categoryList,SIGNAL(currentChanged(QListViewItem*)),
            SLOT(categoryItemSelected(QListViewItem *)));  
    
    connect(categoryList,SIGNAL(doubleClicked(QListViewItem *,const QPoint &, int)),
            SLOT(categoryDoubleClicked(QListViewItem *,const QPoint &, int)));      
    
    global.setBehaviourIfMacOSX(roomList);     
    global.setBehaviourIfMacOSX(categoryList);   
    roomList->clear();
    categoryList->clear();     
    roomList->header()->hide();
    categoryList->header()->hide();     
    categoryList->setSorting(-1);       
     
    roomList->addColumn(QString::number(0)); //,roomList->width());   
    roomList->addColumn(QString::number(1));  
    categoryList->addColumn(QString::number(0));     
 }


C6RoomList::~C6RoomList()
{}

/*!
    \fn C6RoomList::menuSelect(C6ListViewItem *item, const QPoint & pos,int id)
 */
void C6RoomList::menuSelect(QListViewItem *item, const QPoint & pos,int id)
{
    if (item != 0)
    {
        QString tmp = item->text(0);

        if (tmp != SEARCHWAITSTR && tmp !=NO_ROOM_FOUND_MSG)
        {
            int ret = _roomListMenu->exec(pos);

            switch(ret)
            {
            case ROOM_ENTER:
                emit enterRoom(tmp);
                break;
            case ROOM_INVITE:
                inviteInRoom(tmp);
                break;
            case ROOM_PROFILE:
                break;
            }
        }
    }
}

/*!
    \fn C6RoomList::curItemSelected(C6ListViewItem *item)
 */
void C6RoomList::curItemSelected(QListViewItem *item)
{
    if (item != 0)
    {
        QString const& tmp = item->text(0);

        if (tmp != SEARCHWAITSTR && tmp !=NO_ROOM_FOUND_MSG)
        {         
            roomName->setText(tmp);
            roomName->setCursorPosition(0);    
        }         
    }
}

/*!
    \fn C6RoomList::categoryItemSelected(C6ListViewItem *item)
 */
void C6RoomList::categoryItemSelected(QListViewItem *item)
{
    if (item != 0)
    {
        QString const& tmp = item->text(0);
        for (int i=0; i < roomCategory->count(); i++)
        {
            if (roomCategory->text(i).compare(tmp) == 0)
            {
                roomCategory->setCurrentItem(i);
                break;        
            }                     
        }                 
    }
}


/*!
    \fn C6RoomList::enterRoom()
 */
void C6RoomList::enterRoom()
{
    QString tmp = roomName->displayText().stripWhiteSpace();

    if (tmp.length() > 0)
    {      
        emit enterRoom(tmp);
    }
    else
    {
        qApp->beep();
        QMessageBox::warning(this,"Errore","Nessun nome di stanza specificato!",QMessageBox::Ok,QMessageBox::NoButton);
    }            
}


/*!
    \fn C6RoomList::createRoom()
 */
void C6RoomList::createRoom()
{
    QString roomName = createRoomName->displayText().stripWhiteSpace().left(MAX_ROOM_LEN);

    if (roomName.isEmpty() == false)
    {
        QRegExp regex("[^A-Za-z0-9]");
        roomName.replace(regex," ");
        roomName = roomName.stripWhiteSpace();
        
        const QString caption = roomAbout->text().stripWhiteSpace();
        const QString password = roomPassword->text().stripWhiteSpace();       
        emit createRoom(roomName,caption,publicSwitch->isChecked(),roomCategory->currentItem(),
                        password);
    }
    else
    {
        qApp->beep();
        QMessageBox::warning(this,"Errore","Nessun nome di stanza specificato!",QMessageBox::Ok,QMessageBox::NoButton);
    }
}


/*!
    \fn C6RoomList::searchRoom()
 */
void C6RoomList::searchRoom()
{
    if (categoryList->selectedItem() != 0)
    {
        QListViewItemIterator it(categoryList);

        int count = 0;     
        for (; it.current(); ++it )   
        {
            if (it.current() == categoryList->selectedItem())
            {
                break;
            }  
            count++;                   
        }               
        
        unsigned char* tmp = new unsigned char [_category[count].subid.size()*2+1];     
        static const int BASE_ID = 50;
        
        tmp[0] = _category[count].subid.size();    
        tmp[1] = BASE_ID;
        tmp[2] = _category[count].subid[0];
        tmp[3] = BASE_ID+1;
        tmp[4] = _category[count].subid[1];   
             
        int roomSearchAttribute = C6Proto::SEARCH_USER_ROOM;
        
        if (systemSwitch->isChecked())
        {
            roomSearchAttribute = C6Proto::SEARCH_SYSTEM_ROOM; 
        }                 
        
        emit searchFilteredRoom(roomSearchAttribute,tmp);        
        delete [] tmp;      
    }         
}


/*!
    \fn C6RoomList::setWaitResult()
 */
void C6RoomList::setWaitResult()
{
    QString path = C6Global::getInstance().getSkinPath();
    QPixmap& waitSearch = const_cast<QPixmap&>(C6PixmapCache::getInstance().getPixmap(path+"hotsync_busy.png"));
    roomList->clear();
    C6ListViewItem* tmp = new C6ListViewItem(roomList,0,SEARCHWAITSTR);
    tmp->setPixmap(0,waitSearch);
}



/*!
    \fn C6RoomList::setNoResult()
 */
void C6RoomList::setNoResult()
{
    QString path = C6Global::getInstance().getSkinPath();
    QPixmap& flagIcon = const_cast<QPixmap&>(C6PixmapCache::getInstance().getPixmap(path+"flag.png"));

    roomList->clear();
    C6ListViewItem *tmp = new C6ListViewItem(roomList,0,NO_ROOM_FOUND_MSG);
    tmp->setPixmap(0,flagIcon);
}

/*!
    \fn C6RoomList::publicSwitchClicked()
 */
void C6RoomList::publicSwitchClicked()
{
    privateSwitch->setChecked(false);
    publicSwitch->setChecked(true);
}


/*!
    \fn C6RoomList::privateSwitchClicked(()
 */
void C6RoomList::privateSwitchClicked()
{
    privateSwitch->setChecked(true);
    publicSwitch->setChecked(false);
}


/*!
    \fn C6RoomList::nameSwitchClicked()
 */
void C6RoomList::systemSwitchClicked()
{
    systemSwitch->setChecked(true);
    userSwitch->setChecked(false);
    searchRoom(); 
}


/*!
    \fn C6RoomList::profileSwitchClicked()
 */
void C6RoomList::userSwitchClicked()
{
    systemSwitch->setChecked(false);
    userSwitch->setChecked(true);
    searchRoom();
}


/*!
    \fn C6RoomList::profileRoom()
 */
void C6RoomList::profileRoom()
{
    QString tmp = roomName->displayText();
}

/*!
    \fn C6RoomList::doubleClickList(QListViewItem * item)
 */
void C6RoomList::doubleClickList(QListViewItem * item)
{
    QString tmp;

    if (item != 0)
    {
        tmp = item->text(0).stripWhiteSpace();
        emit enterRoom(tmp);
    }
}


/*!
    \fn C6RoomList::setCustomFont()
 */
void C6RoomList::setCustomFont()
{
    C6Global &global=C6Global::getInstance();
    QFont lfont(global.getBaseFont());
    int tmp = lfont.pointSize()-1;
    if (tmp > 2)
    {
        lfont.setPointSize(tmp);
        setFont(lfont);
    }
}

void C6RoomList::aboutClicked()
{
    emit showAbout();
}
    

/*!
    \fn C6RoomList::loadCategory(std::vector<C6Proto::Category>& categoryVector)
 */
void C6RoomList::loadCategoryList(std::vector<C6Proto::Category> const& categoryVector)
{
    static bool first = true;   
    if (first == true)
    {      
        setRoomCategoryCombo(categoryVector);    
        setRoomCategoryList(categoryVector);
        first = false;                  
    }              
}

#include "c6roomlist.moc"

/*!
    \fn C6RoomList::setRoomCategoryCombo(std::vector<C6Proto::Category> const& categoryVector)
 */
void C6RoomList::setRoomCategoryCombo(std::vector<C6Proto::Category> const& categoryVector)
{
    QString tmp;    
    QString description;      
    QStringList list;           
        
    for (unsigned int i=0; i < categoryVector.size(); i++)
    {
        tmp = categoryVector[i].description;
        description = tmp.replace(QChar('#')," - ");      
        list+=description;
    }            
        
    roomCategory->insertStringList(list);    
}


/*!
    \fn C6RoomList::setRoomCategoryList(std::vector<C6Proto::Category> const& categoryVector)
 */
void C6RoomList::setRoomCategoryList(std::vector<C6Proto::Category> const& categoryVector)
{
    C6ListViewItem* root = 0;     
    C6ListViewItem* previous = 0;  
    C6ListViewItem* previousSubItems = 0;           
    
    for (unsigned int i=0; i < categoryVector.size(); i++)
    {
        QString tmp = categoryVector[i].description;
        tmp.replace(QChar('#')," - ");
        
        if (categoryVector[i].subid.size() > 1)
        {
            previousSubItems = new C6ListViewItem(root,previousSubItems,categoryList,tmp);     
        }
        else
        {
            root = new C6ListViewItem(categoryList,previous,tmp);         
            previous = root;
            previousSubItems = root;         
        } 
    }
           
    QListViewItem* first = categoryList->firstChild();   
    if (first != 0)
    {         
        categoryList->setSelected(first,true);   
    }      
}


/*!
    \fn C6RoomList::updateResults(std::vector<C6Proto::RoomSearchResult>& result)
 */
void C6RoomList::updateResults(std::vector<C6Proto::RoomSearchResult>& result)
{
    C6ListViewItem* root = 0;     
    C6ListViewItem* previous = 0;  
    bool addedAtLeastOneItem = false;   
    
    roomList->clear();
    for (unsigned int i=0; i < result.size(); i++)
    {
        C6Proto::RoomAttribute roomAttr;
        roomAttr.unpack(result[i].roomAttribute);
        
        addedAtLeastOneItem = true;         
        int pos = result[i].roomName.find('#');         
        if (pos > -1)
        {
            QListViewItem* temp = roomList->findItem(result[i].roomName.left(pos),0);      
            if (temp == 0)
            {
                root = new C6ListViewItem(roomList,previous,result[i].roomName.left(pos),result[i].roomUsersCount);         
                previous = root;
                (void)new C6ListViewItem(root,root,roomList,result[i].roomName,result[i].roomUsersCount); 
            } 
            else             
            {            
                QListViewItem* myChild = temp->firstChild();
                QListViewItem* prev = 0;            
                while( myChild ) 
                {
                    prev = myChild;        
                    myChild = myChild->nextSibling();
                }            
                
                (void)new C6ListViewItem(temp,prev,roomList,result[i].roomName,result[i].roomUsersCount);          
            }            
        }         
        else
        {
            QListViewItem* temp = roomList->findItem(result[i].roomName,0);                          
            if (temp == 0)
            {                              
                root = new C6ListViewItem(roomList,previous,result[i].roomName,result[i].roomUsersCount);         
                previous = root;     
            }            
        }         
    }      
    
    if (addedAtLeastOneItem == false)
    {
        setNoResult();      
    }         
}


/*!
    \fn C6RoomList::roomSelectionChanged(QListViewItem* item)
 */
void C6RoomList::roomSelectionChanged(QListViewItem* item)
{
    if (item != 0)
    {
        roomName->setText(item->text(0));
    }      
}


/*!
    \fn C6RoomList::inviteInRoom(QString const& roomName)
 */
void C6RoomList::inviteInRoom(QString const& roomName)
{
    C6InviteDialog invite(this);
    connect(&invite,SIGNAL(sendSelected(const QStringList&,const QString&)),
            SLOT(sendSelected(const QStringList&,const QString&)));
    connect(&invite,SIGNAL(showAbout()),SLOT(aboutClicked()));
    invite.exec();

    disconnect(&invite,0,0,0);
}

void C6RoomList::sendSelected(const QStringList &nick,const QString &message)
{
    emit inviteSelected(roomList->selectedItem()->text(0),nick,message);
}

/*!
    \fn C6RoomList::categoryDoubleClicked(QListViewItem *,const QPoint &, int)
 */
void C6RoomList::categoryDoubleClicked(QListViewItem *item,const QPoint &pos , int column)
{
    if (item != 0)
    {
        searchRoom();    
    }      
}
