//
// C++ Implementation: c6global
//
// Description:
//
//
// Author: Giorgio A. <openc6@hotmail.com>, (C) 2005
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "c6global.h"
#include <qstring.h>
#include <qdir.h>
#include <qfile.h>
#include <qtextstream.h>
#include <qstylesheet.h>
#include <qcolor.h>
#include <qfont.h>
#include <qapplication.h>
#include <qfontmetrics.h>
#include <qmap.h>
#include <qstringlist.h>
#include "c6settings.h"
#include "c6logger.h"
#include "macroetc.h"
#include <qstylefactory.h>
#include <qobjectlist.h>
#if (QT_VERSION >= 0x030305)
#if defined(Q_OS_MACX)    
#include <qmacstyle_mac.h>
#include <qstyle.h>
#endif
#endif 


static QApplication* kapplicationInstancePtr= 0;
static C6AbstractPlugin* kapplicationOwner = 0;

C6Global::C6Global():
        _pluginManager(new C6PluginManager())
        ,_netfriendList(0)
        ,_usersManager(new C6UsersManager())      
        , _homeDirPath(QDir::homeDirPath())      
        ,_baseFont()                    
                
{
    _netfriendList = &_usersManager->getNetfriendList();
}

C6Global::~C6Global()
{
    delete _usersManager;    
    delete _pluginManager;
}

/*!
    \fn C6Global::loadNetfriendList()
 */
bool C6Global::loadNetfriendListFromFile()
{
    return(loadNetfriendList(*_usersManager));
}

/*!
    \fn C6Global::loadNetfriendList(C6UsersManager &userlist)
 */
bool C6Global::loadNetfriendList(C6UsersManager &userlist)
{
    QFile file(_homeDirPath+"/"+C6DIR+"/nick.lst");
    bool ret = false;        
    
    if (file.open(IO_ReadOnly))
    {
        QTextStream *stream = new QTextStream(&file);
        loadListFromStream(userlist,stream);
        file.close();
        delete stream;    
        ret = true;    
    }
    else
    {
        loadListFromStream(userlist);
    }
    return ret;   
}


/*!
    \fn C6Global::saveNetfriendList()
                save the current nick list
 */
void C6Global::saveNetfriendList()
{
    QFile file(_homeDirPath+"/"+C6DIR+"/nick.lst" );

    if (file.open( IO_WriteOnly))
    {
        QTextStream stream( &file );
        _usersManager->saveNetfriendList(stream);
        file.close();
    }
}


/*!
    \fn C6Global::loadSpecialList()
 */
void C6Global::loadSpecialList()
{
    QFile file(_homeDirPath+"/"+C6DIR+"/special.lst" );

    if (file.open( IO_ReadOnly))
    {
        QTextStream stream(&file);

        specialFriendList.clear();

        while (!stream.eof())
        {
            specialFriendList+=stream.readLine();
        }

        file.close();
    }
}

bool C6Global::isInSpecialList(QString const &nick)
{
    bool found = false;

    for ( QStringList::Iterator it = specialFriendList.begin();
            it != specialFriendList.end(); ++it )
    {
        if (*it == nick)
        {
            found = true;
            break;
        }
    }
    return(found);
}

/*!
    \fn C6Global::globalInit()
 */
void C6Global::globalInit()
{
    _styleList = QStyleFactory::keys();      
    createDirectories();    
    loadProfileRC();
    loadSpecialList();
    loadAutoRoomList();
    setTabActivated(C6Settings::getInstance().getTabbedChat());
    initStyleSheetItems();
    setInitWidgetStyle();
}

/*!
    \fn C6Global::loadAutoRoomList()
 */
void C6Global::loadAutoRoomList()
{
    QFile roomList(_homeDirPath+"/"+C6DIR+"/autoroom.lst" );
    QString tmp;

    autoRoomList.clear();   
    if (roomList.open( IO_ReadOnly))
    {
        QTextStream stream(&roomList);

        while(!stream.eof())
        {
            tmp = stream.readLine().stripWhiteSpace();
            tmp.remove(QChar(0x0a));

            if (tmp != "")
            {            
                autoRoomList+=tmp;
            }            
        }

        roomList.close();
    }
}

/*!
    \fn C6Global::initStyleSheetItems()
 */
void C6Global::initStyleSheetItems()
{
    QStyleSheet *sh = QStyleSheet::defaultSheet();
    C6Settings &settings = C6Settings::getInstance();

    QStyleSheetItem* it = new QStyleSheetItem(sh,"mymessage");
    it->setColor(QColor("black"));    
    it->setWhiteSpaceMode(QStyleSheetItem::WhiteSpacePre);
    it->setFontSize(_baseFont.pointSize());      
    it->setFontWeight(_baseFont.weight());
    it->setFontFamily(_baseFont.family());          

    it = new QStyleSheetItem(sh, "mynick");
    it->setColor(settings.getForegndColor());
    it->setFontWeight(QFont::Bold);
    it->setFontFamily(settings.getFontStyle());
    it->setFontSize(settings.getFontSize());      
    
    int tmp = _baseFont.pointSize()-1;      

    it = new QStyleSheetItem(sh, "netfmessage");
    it->setColor(QColor("black"));       
    it->setWhiteSpaceMode(QStyleSheetItem::WhiteSpacePre);
    it->setFontSize(_baseFont.pointSize());      
    it->setFontWeight(_baseFont.weight());
    it->setFontFamily(_baseFont.family());          

    it = new QStyleSheetItem(sh, "netfnick");
    it->setColor(settings.getForeNetFriendColor());
    it->setFontWeight(QFont::Bold);
    it->setFontFamily(settings.getFontStyle());
    it->setFontSize(settings.getFontSize());   
       
    it = new QStyleSheetItem(sh, "caption");
    it->setColor(QColor(3,118,231));
    it->setFontWeight(QFont::Bold);
    it->setFontSize(_baseFont.pointSize());
    it->setFontFamily(_baseFont.family());      
    it->setWhiteSpaceMode(QStyleSheetItem::WhiteSpacePre);
   
    
    it = new QStyleSheetItem(sh,"text");
    it->setColor("black");
    it->setFontSize(tmp);   
    it->setFontWeight(QFont::Normal);
    it->setFontFamily(_baseFont.family());    
    it->setWhiteSpaceMode(QStyleSheetItem::WhiteSpacePre);
    
    it = new QStyleSheetItem(sh,"smessage");
    it->setColor(settings.getForeMessageColor());
    it->setWhiteSpaceMode(QStyleSheetItem::WhiteSpacePre);   
    it->setFontSize(tmp);      
    it->setFontWeight(QFont::Normal);
    it->setFontFamily(_baseFont.family());       
    
    sh->item("a")->setColor(Qt::blue);
    it = new QStyleSheetItem(sh,"cfouttag");  
    it = new QStyleSheetItem(sh,"cfintag");   
    it = new QStyleSheetItem(sh,"mynickpre"); 
    it->setFontWeight(QFont::Bold);              
    it = new QStyleSheetItem(sh,"othernickpre");
    it->setFontWeight(QFont::Bold);   
}





/*!
    \fn C6Global::loadProfile()
 */
void C6Global::loadProfileRC()
{
    QFile file(getSharePath()+"/profilerc");

    if ( file.open( IO_ReadOnly ) )
    {
        QTextStream stream( &file );
        while ( !stream.atEnd() )
        {
            profilerc.append(stream.readLine());
        }
        file.close();
    }
}

/*!
    \fn C6Global::getProfileEntryIndex()
 */
int C6Global::getProfileEntryIndex(QStringList const & list,QString const & Entry)
{
    bool found = false;
    unsigned int i;

    for (i=0; (i < list.size()) && !found; i++)
    {
        if (list[i].contains(Entry))
        {
            found = true;
        }
    }
    return(found ? static_cast<int>(i-1) : -1);
}

/*!
    \fn C6Global::initialize()
 */
void C6Global::initialize()
{
    globalInit();
}

C6AbstractPlugin* C6Global::buildPlugin(QString const & pluginName,bool startKapp)
{
    C6AbstractPlugin *plugin = 0;

    if (QFile::exists(pluginName) == true)
    {
        C6PlugInFactory *pf = _pluginManager->getFactory(pluginName);

        if (pf !=0)
        {
            plugin = pf->getPluginInstance();

            if ((plugin->isForKde() == true) && (startKapp == true))
            {
                if (kapplicationInstancePtr == 0)
                {
                    kapplicationOwner = plugin;
                    kapplicationInstancePtr = plugin->createKApplication();
                }
            }
        }
        else
        {
            qWarning("C6Global: buildPlugin cant create factory plugin for %s\n",pluginName.latin1());
        }
    }
    else
    {
        qWarning("C6Global: buildPlugin %s doesn't exist\n",pluginName.latin1());
    }
    return(plugin);
}

QApplication* C6Global::initPlugin(C6AbstractPlugin* plugin)
{
    QApplication *pQApp=0;

    if (plugin !=0)
    {
        plugin->initialize();
        pQApp = plugin->getKdeEntryPoint();
    }

    return(pQApp);
}

void C6Global::loadPlugin(QString const & pluginName)
{
    C6AbstractPlugin* pl = buildPlugin(pluginName);

    if (pl != 0)
    {
        initPlugin(pl);
    }
}

void C6Global::unloadPlugin(const QString fname)
{
    C6PlugInFactory *pf = _pluginManager->getFactory(fname);

    if (pf != 0)
    {
        C6AbstractPlugin *plugin = pf->getPluginInstance();

        if (plugin->isForKde() == true)
        {
            if (plugin != kapplicationOwner)
            {
                plugin->setDestroy();
            }
        }
        pf->destroyPlugin();
        _pluginManager->destroy(fname);
    }
}


/*!
    \fn C6Global::loadPluginList()
 */
void C6Global::loadPluginList()
{
    QFile file(_homeDirPath+"/"+C6DIR+"/plugin.lst" );

    if (file.open( IO_ReadOnly))
    {
        QTextStream stream( &file );
        QString line;

        while ( !stream.eof() )
        {
            line = stream.readLine().stripWhiteSpace();                      // line of text excluding '\n'
            if (line.length() > 0)
            {
                _loadedPlugin.append(line);
            }
        }
        file.close();
    }
}

QApplication* C6Global::getKappInstance()
{
    return(kapplicationInstancePtr);
}


/*!
    \fn C6Global::getLoadedPlugin()
 */
QStringList C6Global::getLoadedPlugin()
{
    return(_pluginManager->getFactoryName());
}


/*!
    \fn C6Global::getPluginInstance()
 */
C6AbstractPlugin* C6Global::getPluginInstance(QString const & fname)
{
    C6PlugInFactory *pf = _pluginManager->getFactory(fname);
    C6AbstractPlugin *plugin = 0;

    if (pf != 0)
    {
        plugin = pf->getPluginInstance();
    }

    return(plugin);
}

QStringList C6Global::getLoadedPluginName()
{
    QStringList pname = getLoadedPlugin();
    QStringList out;

    for (unsigned int i=0; i < pname.count(); i++)
    {
        C6AbstractPlugin *plugin = getPluginInstance(pname[i]);
        if (plugin != 0)
        {
            out.append(plugin->getName());
        }
    }
    return (out);
}

void C6Global::addUser(QString const & group,QString const & nick)
{
    _usersManager->addUser(group,nick);
}

void C6Global::addUser(QString const & group,QString const & user,QString const & nick)
{
    _usersManager->addUser(group,user,nick);
}

const C6ListHash& C6Global::getNetfriendList() const
{
    return *_netfriendList;
}

void C6Global::removeUser(QString const & nick)
{
    _usersManager->removeUser(nick);
}

const QStringList C6Global::getGroupUsers(QString const &group)
{
    return(_usersManager->getGroupUsers(group));
}

void C6Global::setAllUsersOffline()
{
    _usersManager->setAllUsersOffline();
}

C6Users*  C6Global::getC6UserPtr(const QString &nick)
{
    _usersManager->getC6UserPtr(nick);
}

QStringList C6Global::getAllUsers()
{
    return(_usersManager->getAllUsers());
}

bool C6Global::groupIsPresent(QString const &group)
{
    return(_usersManager->groupIsPresent(group));
}

void C6Global::addGroup(QString const &group)
{
    _usersManager->addGroup(group);
}

bool  C6Global::removeGroup(QString const &group)
{
    return(_usersManager->removeGroup(group));
}

QStringList C6Global::getAllGroups()
{
    return(_usersManager->getAllGroups());
}

 bool  C6Global::isBlackListed(QString const & nick)
{
    return(_usersManager->isBlackListed(nick));
}      

const QStringList C6Global::getBlackListUsers()
{
    return(_usersManager->getBlackListUsers());
}      

const QString C6Global::getUserGroupName(QString const &user)
{
    return(_usersManager->getUserGroupName(user));    
}      

/*!
    \fn C6Global::renameGroup(const QString &oldname,const QString &newname)
 */
bool C6Global::renameGroup(const QString &oldname,const QString &newname)
{
    return(_usersManager->renameGroup(oldname,newname));   
}

C6Users::C6UsersList& C6Global::getC6UsersFromGroup(QString const &group)
{
    return(_usersManager->getC6UsersFromGroup(group));     
}      

void  C6Global::setBehaviourIfMacOSX(QWidget *widget)
{
#if (QT_VERSION >= 0x030305)   
#if defined(Q_OS_MACX)   
    QStyle *style = &QApplication::style();
    QMacStyle *macstyle = dynamic_cast<QMacStyle*>(style);   
    
    if  (macstyle != 0)
    {
        QMacStyle::setFocusRectPolicy(widget,QMacStyle::FocusDisabled);    
    }          
#endif
#endif   
}      



/*!
    \fn C6Global::createDirectories()
 */
void C6Global::createDirectories()
{
    QDir curdir(C6Settings::getInstance().getFileReceivePath());

    if (!curdir.exists())
    {
        curdir.mkdir("");
    }   
}


/*!
    \fn C6Global::setFirstBoot(bool set)
 */
void C6Global::setFirstBoot(bool set)
{
    C6Settings::getInstance().setFirstBoot(set);
}


/*!
    \fn C6Global::getStyleList()
 */
const QStringList & C6Global::getStyleList()
{
    return(_styleList);
}

/*!
    \fn C6Global::setWidgetStyle
 */
void C6Global::setWidgetStyle(QString const &style)
{
    if (style.length() > 0)
    {          
        qApp->setStyle(style);       
    }      
}


/*!
    \fn C6Global::setInitWidgetStyle()
 */
void C6Global::setInitWidgetStyle()
{
    if (C6Settings::getInstance().getStyleSwitch() == true)
    {
        setWidgetStyle(C6Settings::getInstance().getWidgetStyle()); 
    }      
}

const QString C6Global::getBlackListGroupName()
{
    return(_usersManager->getBlackListGroupName());   
}
      
void C6Global::clearUsersList()
{
    _usersManager->clear();
}   
   
bool C6Global::isTheBlackList(QString const &group)
{
    return(_usersManager->isTheBlackList(group));   
}         
   
/*!
    \fn C6Global::loadListFromStream(C6UsersManager &userlist,QTextStream* stream)
*/

void C6Global::loadListFromStream(C6UsersManager &userlist,QTextStream* stream)
{
    QString line;
    QString groupToHash;
    
    if (stream != 0)
    {
        while (!stream->eof())
        {
            line = stream->readLine().stripWhiteSpace(); 
            if (line.contains("[") == true)
            {
                groupToHash = line.mid(1,line.length()-2);
                userlist.addGroup(groupToHash);            
            }
            else
            {
                userlist.addUser(groupToHash,line);
            }
        }
    }
    else   
    {   
        // add AMICI if empty 
        userlist.addGroup(userlist.getFriendListGroupName());   
    }       
}

bool C6Global::mergeLocalListToServerSide()
{
    C6UsersManager localUsersManager;
    bool ret = false;    
    
    if (loadNetfriendList(localUsersManager) == true)
    {      
        _usersManager->update(localUsersManager);
        ret = true;    
    }      
    return ret;   
}      

/*!
    \fn C6Global::addToWhiteList(QString const &user,QString const &nick)
 */
void C6Global::addToWhiteList(QString const &user,QString const &nick)
{
    _usersManager->addToWhiteList(user,nick);
}

/*!
    \fn C6Global::addToWhiteList(QString const &user,QString const &nick)
 */
void C6Global::addToWhiteList(QString const &nick)
{
    _usersManager->addToWhiteList(nick);
}

/*!
    \fn C6Global::getWhiteListUsers()
 */
const QStringList C6Global::getWhiteListUsers()
{
    return(_usersManager->getWhiteListUsers());
}


/*!
    \fn C6Global::removeFromWhiteList(Qstring const & nick)
 */
void C6Global::removeFromWhiteList(QString const & nick)
{
    _usersManager->removeFromWhiteList(nick); 
}


/*!
    \fn C6Global::isWhiteListed(QString const &nick)
 */
bool C6Global::isWhiteListed(QString const &nick)
{
    return(_usersManager->isWhiteListed(nick));
}


/*!
    \fn C6Global::getWhiteListGroupName()
 */
QString C6Global::getWhiteListGroupName()
{
    return(_usersManager->getWhiteListGroupName());
}


/*!
    \fn C6Global::saveIdentity(QString nick, QString pw)
 */
void C6Global::saveCurrentIdentity(QString const &loginId, QString const &pw,QString const &messageODD)
{
    const QString password = (pw != QString::null) ? pw : "none";
    
    saveAccountDetailsWithKey(loginId,"General","Password",password);
    saveAccountDetailsWithKey(loginId,C6Settings::getInstance().getCurrentIdentity(),"Message",messageODD);           
}


/*!
    \fn C6::getIdentityPassword(QString id)
 */
QString C6Global::getCurrentIdentityPassword(QString const &id)
{
    const QString passw = loadAccountDetailsFromKey(id,"General","Password");    
              
    if (passw.compare("none") == 0)
    {
        return(QString::null);      
    }          
    else
    {      
        return(passw);
    }      
}

QString C6Global::getCurrentMessageODDay(QString const &loginId,QString const &nick)
{
    return(loadAccountDetailsFromKey(loginId,nick,"Message"));   
}      

void C6Global::saveCurrentMessageODDay(QString const &loginId,QString const &message)
{
    saveAccountDetailsWithKey(loginId,C6Settings::getInstance().getCurrentIdentity(),"Message",message);                 
}      

QString C6Global::loadAccountDetailsFromKey(QString const& id,QString const& key,QString const& value)
{
    QFile file(QDir::homeDirPath()+"/"+C6DIR+"/"+C6USERSDIR+"/"+id+".rc");
    QTextStream filestream(&file);
    QString ret = "none";
    bool found = false;    
    
    if (!file.open(IO_ReadOnly))
    {
        qDebug("Cannot open %s\n",file.name().latin1());
    }
    else
    {      
        while (!filestream.atEnd())
        {          
            QString line = filestream.readLine();
            if (found == false)
            {                
                if (line.compare("["+key+"]") == 0)
                {
                    found = true;    
                }
            }
            else
            {
                if (line.contains("[") > 0)
                {
                    break;     
                }         
                else
                {                           
                    if (line.section(QChar('='),0,0).compare(value) == 0)
                    {
                        ret = line.section(QChar('='),1);
                        break;        
                    }
                }            
            }                        
        }  
        
        file.close();    
    }   
    return(ret);
}

void C6Global::saveAccountDetailsWithKey(QString const& id,QString const& section,QString const& key,QString const& value)
{
    QFile file(QDir::homeDirPath()+"/"+C6DIR+"/"+C6USERSDIR+"/"+id+".rc");
    QTextStream filestream(&file);
    QStringList lines;   
    
    if (file.exists() == true)
    {          
        if (!file.open(IO_ReadOnly))
        {
            qDebug("Cannot open %s\n",file.name().latin1());
            return;
        }
        
        while (!filestream.atEnd())
        {          
            lines+= filestream.readLine();
        }  
        
        file.close();        
    }
    
    bool foundSection = false;    
    bool foundKey = false;
    QStringList::iterator it;
    
    for (it=lines.begin(); it != lines.end(); it++)
    {
        if (foundSection == false)
        {             
            if ((*it).compare("["+section+"]") == 0)
            {
                foundSection = true;    
            }
        }
        else
        {
            if ((*it).startsWith("[") > 0 && (*it).endsWith("]"))
            {
                break;    
            }    
            else                
            {            
                if ((*it).section(QChar('='),0,0).compare(key) == 0)
                {
                    (*it) = (*it).section(QChar('='),0,0)+"="+value;     
                    foundKey = true;    
                    break;
                }                    
            }         
        }                             
    }          
   
    if (foundSection == false)
    {
        lines+="["+section+"]";
        lines+=key+"="+value;          
    }
    else
    {      
        if(foundKey == false)
        {               
            lines.insert(it,key+"="+value);     
        }      
    }   
        
    if (!file.open(IO_Truncate |IO_WriteOnly))
    {
        qDebug("Cannot open %s\n",file.name().latin1());
        return;
    }
        
    for (unsigned int i=0; i < lines.size(); i++)
    {
        filestream << lines[i] << "\n"; 
    }        
    
    file.close();    
}



/*!
    \fn C6Global::localNetfriendListExists()
 */
bool C6Global::localNetfriendListExists()
{
    return(QFile::exists (_homeDirPath+"/"+C6DIR+"/nick.lst"));
}


/*!
    \fn C6Global::isFirstLoginAttempt(QString const &loginId,QString const &nick)
 */
bool C6Global::isFirstAccountLoginAttempt(QString const &loginId)
{
    bool ret = false;    
    const QString firstLoginValue = loadAccountDetailsFromKey(loginId,
          C6Settings::getInstance().getCurrentIdentity(),"FirstLogin"); 
    
    if (firstLoginValue.compare("none") == 0)
    {
        ret = true; 
    }         
     
    return(ret);   
}

/*!
    \fn C6Global::setFirstLoginAttempt(QString const &loginId,QString const &nick)
 */
void C6Global::setFirstAccountLoginAttempt(QString const &loginId)
{
    saveAccountDetailsWithKey(loginId,C6Settings::getInstance().getCurrentIdentity(),"FirstLogin","yes");   
}