/***************************************************************************
 *   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 "chatcore.h"
#include "globals.h"

#include <QMapIterator>
#include <QApplication>

#include "inputtextwgt.h"
#include "qchatsettings.h"
#include "userinfo.h"
#include "userprofile.h"
#include "channelwgt.h"

#include "userlisticonformat.h"

//\*****************************************************************************
bool ChatCore::initSettings(QString dirName)
{
  QString home = homePath();
  QFile   file;
  QDir    settingsDir(home);
  QString path;


  if(!dirName.isEmpty())
  {
     path            = dirName + QString("/settings.ini"     );
     m_qsettings      = new QSettings(path, QSettings::IniFormat);
  }
  else if(home.isEmpty())
  {
    return false;
  }
  else
  {
     dirName = QString("%1/%2").arg(home).arg(".qchat");

     if(!QDir(dirName).exists())
     {
       printf("[ChatCore::initSettings]: settingsDir does not exists...\n");
       if(settingsDir.mkdir(".qchat"))
         printf(" created!\n");
       else
       {
         printf(" and cannot create :(\n");
         return false;
       }
     }
     // TODO sdelat' proverku na readOnly i v etom sluchae vyvodit' dialog vybora faila nastroek

     path            = dirName + QString("/settings.ini");
     m_qsettings     = new QSettings(path, QSettings::IniFormat);

     if(!QDir(QChatSettings::loggingDir()).exists())
     {
       printf("[ChatCore::initSettings]: chatLogDir does not exists...\n");
       if(QDir("").mkpath(QChatSettings::loggingDir()))
         printf(" created!\n");
       else
       {
         printf(" and cannot create :(\n");
         QChatSettings::setLoggingDir("");
       }
     }
  }

  printf("[ChatCore::initSettings]: settingsDir = %s\n", dirName.toLocal8Bit().data());

  QChatSettings::setSettingsDir(dirName);

  if(QFile::exists(dirName + "/Charmap"))
    InputTextWgt::initChars(dirName + "/Charmap");
#ifdef Q_OS_LINUX
  else if(QFile::exists(QApplication::applicationDirPath() + "/../share/qchat/Charmap"))
    InputTextWgt::initChars(QCoreApplication::applicationDirPath() + "/../share/qchat/Charmap");
#else
  else if(QFile::exists(QApplication::applicationDirPath() + "/Charmap"))
    InputTextWgt::initChars(QApplication::applicationDirPath() + "/Charmap");
#endif

  return true;
}
//\*****************************************************************************
void ChatCore::slot_saveSettings()
{
  saveSettings(false);
}

void ChatCore::saveSettings(bool on_quit)
{
  // FIXME !!!
  settings()->setMode(QChatSettings::Serverless);

  QByteArray data;
  QByteArray ba;
  QBuffer    buffer;

  qDebug("[ChatCore::saveSettings]");

  QChatSettings::settings()->saveGeneralOptions(m_qsettings);

  m_qsettings->beginGroup("Network");

  m_qsettings->setValue    ("Broadcast"       , QChatSettings::settings()->realBroadcast().toString());

  QStringList ipList;
  foreach(QHostAddress ip, QChatSettings::settings()->ipList())
    ipList.append(ip.toString());
  m_qsettings->setValue("IPList", ipList);

  m_qsettings->endGroup  ();

  //***************************
  QMapIterator<QString, UserProfile*> pr(m_profiles);
  QStringList profiles;
  while (pr.hasNext())
  {
    pr.next();
    writeProfile(pr.value());
    profiles << pr.key();
  }
  //**********************************
  m_qsettings->setValue("ProfileNames", profiles);
  m_qsettings->setValue("LastProfile" , m_currentProfile->name());
  m_qsettings->setValue("Language"    , m_lang);

  if(m_chatWgt && on_quit)
  {
    m_qsettings->setValue("Geometry", m_chatWgt->saveGeometry());
    m_qsettings->setValue("MainWindowState", m_chatWgt->saveState());

    QList<ChannelWgt*> l = m_chatWgt->channels();

    foreach(ChannelWgt* c, l)
      setChannelState(c->name(), c->saveState());
  }

  m_qsettings->setValue("ChannelsStates", QStringList(m_channelsStates.keys()));

  QMapIterator<QString, QByteArray> ch(m_channelsStates);
  while (ch.hasNext())
  {
    ch.next();
    m_qsettings->setValue(ch.key() + "ChannelState", ch.value());
  }

  m_qsettings->sync();

  // FIXME !!!
  settings()->setMode((QChatSettings::Mode)m_mode);
}
//\*****************************************************************************
void ChatCore::slot_loadSettings()
{
  QNetworkAddressEntry addr;
  QString str;
  QStringList profiles;

  QChatSettings::settings()->loadGeneralOptions(m_qsettings);

  m_qsettings->beginGroup("Network");

  if(!QChatSettings::settings()->boolOption("AllowDifferentPorts"))
    QChatSettings::settings()->setOption("OutputPort", QChatSettings::settings()->option("InputPort"));

  //*******************************
  addr.setIp(QHostAddress(QString(m_qsettings->value("IP").toByteArray().data ())));
  addr.setBroadcast(QHostAddress(QString(m_qsettings->value("Broadcast").toByteArray().data ())));

  QStringList ipList;
  ipList = m_qsettings->value("IPList").toStringList();
  foreach(QString ip, ipList)
    QChatSettings::addIpListEntry(QHostAddress(ip));

  QList<QNetworkInterface> all_i = QNetworkInterface::allInterfaces();
  QList<QNetworkAddressEntry> valid_a;

  // get all valid(that can broadcast) interfaces
  foreach(QNetworkInterface i, all_i)
    foreach(QNetworkAddressEntry a, i.addressEntries())
    {
      if(a.broadcast().isNull())
        continue;

       valid_a.append(a);
    }

  // this will be used to determine do we need to
  // warning user about problems with network settings
  m_needCheckIp = 1 + valid_a.isEmpty();

  // if network settings was not set yet
  // or they are is broken we are try to set correct ones
  if(addr.ip().isNull() && !valid_a.isEmpty())
    addr = valid_a[0];
  else if(addr.broadcast().isNull() && !valid_a.isEmpty())
    addr.setBroadcast(valid_a[0].broadcast());

  // are network settings corresponds any of existing interface?
  foreach(QNetworkAddressEntry a, valid_a)
    if((a.ip() == addr.ip()) && (a.broadcast() == addr.broadcast()))
    {
      m_needCheckIp = 0;
      break;
    }

  QChatSettings::settings()->setOption("IP", addr.ip().toString());
  QChatSettings::settings()->setOption("Broadcast", addr.broadcast().toString());

  QHostAddress tmp;

  tmp = QHostAddress(m_qsettings->value("CustomIP").toString());
  if(!tmp.isNull())
    addr.setIp(tmp);

  tmp = QHostAddress(m_qsettings->value("CustomBroadcast").toString());
  if(!tmp.isNull())
    addr.setBroadcast(tmp);

  QChatSettings::settings()->setOption("CustomIP", addr.ip().toString());
  QChatSettings::settings()->setOption("CustomBroadcast", addr.broadcast().toString());
  //*******************************

  m_qsettings->endGroup();

  //***************************
  profiles   = m_qsettings->value("ProfileNames", QStringList()).toStringList();
  str        = m_qsettings->value("LastProfile" , "Default").toString();
  m_geometry = m_qsettings->value("Geometry").toByteArray();
  m_state    = m_qsettings->value("MainWindowState").toByteArray();
  m_lang     = m_qsettings->value("Language").toString();

  QStringList channels = m_qsettings->value("ChannelsStates", QStringList()).toStringList();

  foreach(QString s, channels)
    m_channelsStates.insert(s, m_qsettings->value(s + "ChannelState").toByteArray());

//   m_channelsStates.insert("Main", m_qsettings->value("MainChannelState").toByteArray());

  if(profiles.isEmpty())
    m_profiles.insert("Default", readProfile("Default"));
  else
    foreach(QString s, profiles)
      m_profiles.insert(s, readProfile(s));

  slot_loadProfile(str);
}
//\*****************************************************************************
UserProfile* ChatCore::readProfile(const QString & name)
{
  UserInfo*    info    = new UserInfo;
  QChatSettings* prefs   = new QChatSettings;
  UserProfile* profile = new UserProfile(name, prefs, info);
  QByteArray   ba;

  m_qsettings->beginGroup("Profiles");

  m_qsettings->beginGroup(name);

  prefs->loadOptions(m_qsettings);

  m_qsettings->beginGroup("Warnings");

  m_qsettings->endGroup();//  m_qsettings->beginGroup("Warnings");

  m_qsettings->beginGroup("UserInfo");

  info->setGender     (m_qsettings->value("Gender"     ,  0).toInt());
  info->setNickname   (m_qsettings->value("NickName"   , QString(QHostInfo::localHostName())).toString());
  info->setLastName   (m_qsettings->value("LastName"   , "").toString());
  info->setFirstName  (m_qsettings->value("FirstName"  , "").toString());
  info->setSecondName (m_qsettings->value("SecondName" , "").toString());
  info->setDateOfBorn (m_qsettings->value("DateOfBorn" , "").toDate  ());
  info->setAddress    (m_qsettings->value("Address"    , "").toString());
  info->setHomePhone  (m_qsettings->value("HomePhone"  , "").toString());
  info->setWorkPhone  (m_qsettings->value("WorkPhone"  , "").toString());
  info->setMobilePhone(m_qsettings->value("MobilePhone", "").toString());
  info->setE_mail     (m_qsettings->value("e-mail"     , "").toString());
  info->setICQ        (m_qsettings->value("ICQ"        , "").toString());
  info->setHomepage   (m_qsettings->value("Homepage"   , "").toString());
  info->setAboutInfo  (m_qsettings->value("About"      , "").toString());

  m_qsettings->endGroup();//  m_qsettings->beginGroup("UserInfo");

  info->setPhoto  (m_qsettings->value("Photo"  , "/").toString());
  info->setPicture(m_qsettings->value("Picture", "/").toString());

  m_qsettings->beginGroup("Preferences");

  QColor c(Qt::red);
  ba = QByteArray();
  ba = m_qsettings->value("MyMessagesColor", QByteArray().append(c.red())
                                                        .append(c.green())
                                                        .append(c.blue())).toByteArray();
  prefs->setMyColor(QColor((quint8)ba[0], (quint8)ba[1], (quint8)ba[2]));
  c  = QColor(Qt::gray);
  ba = QByteArray();
  ba = m_qsettings->value("SystemMessagesColor", QByteArray().append(c.red())
                                                            .append(c.green())
                                                            .append(c.blue())).toByteArray();
  prefs->setSysColor(QColor((quint8)ba[0], (quint8)ba[1], (quint8)ba[2]));
  c  = QColor(Qt::black);
  ba = QByteArray();
  ba = m_qsettings->value("BaseColor"       , QByteArray().append(c.red())
                                                         .append(c.green())
                                                         .append(c.blue())).toByteArray();
  prefs->setBaseColor(QColor((quint8)ba[0], (quint8)ba[1], (quint8)ba[2]));

  prefs->setSmilesThemePath  (m_qsettings->value("SmilesTheme", QChatSettings::defaultSmilesDir()).toString());
  prefs->setSmilesPolicy     ((QChatSettings::SmilesPolicy)m_qsettings->value("SmilesPolicy", (int)QChatSettings::AlwaysUseSmilesFromSender).toInt());

  prefs->setExecuteCommandOnIncomingMsg(m_qsettings->value("ExecuteCommandOnIncomingMessage", "").toString());

  prefs->setNHistoryMsgs(m_qsettings->value("MaximumMessagesHistoryNumber", -1).toInt());
  prefs->setHistoryReqTimeout(m_qsettings->value("MessagesHistoryRequestTimeout", 5000).toInt()); // msecs

  prefs->setUsersListRefreshInterval(m_qsettings->value("UsersListRefreshInterval", 60).toInt()); // secs
  prefs->setUsersListDeepRefreshInterval(m_qsettings->value("UsersListDeepRefreshInterval", 600).toInt()); // secs

  prefs->iconFormat()->restore(m_qsettings->value("UserListIconFormat", UserListIconFormat().save()).toByteArray());
  prefs->setToolbarIconsSize(m_qsettings->value("ToolBarIconsSize", 22).toInt());

  m_qsettings->beginGroup("MessageFilter");

  prefs->messageFilter()->load(m_qsettings);

  m_qsettings->endGroup();

  m_qsettings->endGroup();//  m_qsettings->beginGroup("QChatSettings");

  m_qsettings->beginGroup("Shortcuts");

  QStringList all_shortcuts = m_qsettings->value("AllShortcuts").toStringList();
  QStringList shortcuts;

  foreach(QString name, all_shortcuts)
  {
    if(!prefs->shortcutExists(name))
      continue;

    shortcuts = m_qsettings->value(name).toStringList();

    bool first = true;

    foreach(QString shrtct, shortcuts)
    {
      // if we have >= 1 non empty sequences for action we need to reset default sequences
      if(!QKeySequence(shrtct).toString().isEmpty() && first)
      {
        first = false;
        prefs->clearShortcut(name);
      }

      prefs->addShortcut(name, QKeySequence(shrtct));
    }
  }

  m_qsettings->endGroup();//  m_qsettings->beginGroup("Shortcuts");

  m_qsettings->beginGroup("StatusDescriptions");

  prefs->setStatusDescription(m_qsettings->value("Ready4Chat").toString(), Globals::READY4CHAT);
  prefs->setStatusDescription(m_qsettings->value("Free"      ).toString(), Globals::FREE);
  prefs->setStatusDescription(m_qsettings->value("Busy"      ).toString(), Globals::BUSY);
  prefs->setStatusDescription(m_qsettings->value("Dnd"       ).toString(), Globals::DND);
  prefs->setStatusDescription(m_qsettings->value("Inactive"  ).toString(), Globals::INACTIVE);
  prefs->setStatusDescription(m_qsettings->value("Away"      ).toString(), Globals::AWAY);

  prefs->setStatusDescriptions(m_qsettings->value("DescriptionsHistory").toStringList());

  m_qsettings->endGroup();//  m_qsettings->beginGroup("StatusDescriptions");

  m_qsettings->beginGroup("NowListening");

  prefs->setNlMode(m_qsettings->value("SendWithMessage", false).toBool() +
                   m_qsettings->value("SetInStatus"    , false).toBool() * 2);

  m_qsettings->endGroup();//  m_qsettings->beginGroup("NowListening");

  m_qsettings->endGroup();//  m_qsettings->beginGroup(name);

  m_qsettings->endGroup();// m_qsettings->beginGroup("Profiles");

  return profile;
}
//\*****************************************************************************
void ChatCore::writeProfile(const UserProfile* profile)
{
  QChatSettings* prefs = profile->prefs();
  UserInfo*    info  = profile->info();
  QByteArray bpic;
  QByteArray ba;
  QByteArray data;
  QBuffer    buffer;

  m_qsettings->beginGroup("Profiles");

  m_qsettings->beginGroup(profile->name());

  prefs->saveOptions(m_qsettings);

  m_qsettings->setValue("Photo"              , info->photoFilename  ());
  m_qsettings->setValue("Picture"            , info->pictureFilename());

  m_qsettings->beginGroup("Warnings");

  m_qsettings->endGroup();//  m_qsettings->beginGroup("Warnings");


  m_qsettings->beginGroup("UserInfo");

  m_qsettings->setValue("Gender"       , info->gender());
  m_qsettings->setValue("NickName"     , info->nickname());
  m_qsettings->setValue("LastName"     , info->lastName());
  m_qsettings->setValue("FirstName"    , info->firstName());
  m_qsettings->setValue("SecondName"   , info->secondName());
  m_qsettings->setValue("DateOfBorn"   , info->dateOfBorn());
  m_qsettings->setValue("Address"      , info->address());
  m_qsettings->setValue("HomePhone"    , info->homePhone());
  m_qsettings->setValue("WorkPhone"    , info->workPhone());
  m_qsettings->setValue("MobilePhone"  , info->mobilePhone());
  m_qsettings->setValue("e-mail"       , info->e_mail());
  m_qsettings->setValue("ICQ"          , info->icq());
  m_qsettings->setValue("Homepage"     , info->homepage());
  m_qsettings->setValue("About"        , info->aboutInfo());

  m_qsettings->endGroup();//  m_qsettings->beginGroup("UserInfo");

  m_qsettings->beginGroup("Preferences");

  ba = QByteArray();
  ba = QByteArray().append(prefs->myColor().red())
                   .append(prefs->myColor().green())
                   .append(prefs->myColor().blue());
  m_qsettings->setValue("MyMessagesColor"         , ba);

  ba = QByteArray();
  ba = QByteArray().append(prefs->sysColor().red())
                   .append(prefs->sysColor().green())
                   .append(prefs->sysColor().blue());
  m_qsettings->setValue("SystemMessagesColor"     , ba);

  ba = QByteArray();
  ba = QByteArray().append(prefs->baseColor().red())
                   .append(prefs->baseColor().green())
                   .append(prefs->baseColor().blue());
  m_qsettings->setValue("BaseColor"               , ba);

  m_qsettings->setValue("SmilesTheme"             , prefs->smilesThemePath());
  m_qsettings->setValue("SmilesPolicy"            , prefs->smilesPolicy());

  m_qsettings->setValue("ExecuteCommandOnIncomingMessage"  , prefs->executeCommandOnIncomingMsg());

  m_qsettings->setValue("MaximumMessagesHistoryNumber"   , prefs->nHistoryMsgs());
  m_qsettings->setValue("MessagesHistoryRequestTimeout"  , prefs->historyReqTimeout());

  m_qsettings->setValue("UsersListRefreshInterval"       , prefs->usersListRefreshInterval());
  m_qsettings->setValue("UsersListDeepRefreshInterval"   , prefs->usersListDeepRefreshInterval());

  m_qsettings->setValue("UserListIconFormat"             , prefs->iconFormat()->save());
  m_qsettings->setValue("ToolBarIconsSize"               , prefs->toolbarIconsSize());

  m_qsettings->beginGroup("MessageFilter");

  prefs->messageFilter()->save(m_qsettings);

  m_qsettings->endGroup();

  m_qsettings->endGroup();//  m_qsettings->beginGroup("QChatSettings");

  m_qsettings->beginGroup("Shortcuts");

  m_qsettings->setValue("AllShortcuts", QStringList(prefs->allShortcuts().keys()));

  QMapIterator< QString, QList<QKeySequence> > sh(prefs->allShortcuts());
  QStringList shortcuts;

  while(sh.hasNext())
  {
    sh.next();

    shortcuts.clear();

    foreach(QKeySequence seq, sh.value())
      shortcuts.append(seq.toString());

    m_qsettings->setValue(sh.key(), shortcuts);
  }

  m_qsettings->endGroup();//  m_qsettings->beginGroup("Shortcuts");

  m_qsettings->beginGroup("StatusDescriptions");

  m_qsettings->setValue("Ready4Chat", prefs->statusDescription(Globals::READY4CHAT));
  m_qsettings->setValue("Free"      , prefs->statusDescription(Globals::FREE));
  m_qsettings->setValue("Busy"      , prefs->statusDescription(Globals::BUSY));
  m_qsettings->setValue("Dnd"       , prefs->statusDescription(Globals::DND));
  m_qsettings->setValue("Inactive"  , prefs->statusDescription(Globals::INACTIVE));
  m_qsettings->setValue("Away"      , prefs->statusDescription(Globals::AWAY));

  m_qsettings->setValue("DescriptionsHistory", prefs->statusDescriptions());

  m_qsettings->endGroup();// m_qsettings->beginGroup("StatusDescriptions");

  m_qsettings->beginGroup("NowListening");

  m_qsettings->setValue("SendWithMessage", prefs->nlMode() & 1);
  m_qsettings->setValue("SetInStatus"    , prefs->nlMode() & 2);
  m_qsettings->setValue("Format"         , prefs->strOption("NLFormat"));

  m_qsettings->endGroup();//  m_qsettings->beginGroup("NowListening");

  m_qsettings->endGroup();// m_qsettings->beginGroup(profile->name());

  m_qsettings->endGroup();// m_qsettings->beginGroup("Profiles");

}
//\*****************************************************************************
