/***************************************************************************
 *   Copyright (C) 2007 by Anistratov Oleg                                 *
 *   ower86@gmail.com                                                      *
 *                                                                         *
 *   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 "singlemsgshistorymodel.h"

#include <QDateTime>

#include "singlemsgshistory.h"
#include "messagetreeitem.h"
#include "singlemessage.h"

SingleMsgsHistoryModel::SingleMsgsHistoryModel(QObject* parent) :
  TreeModel(parent),
  m_currentLayout(IpUserDate),
  m_incoming(NULL),
  m_outgoing(NULL),
  m_sortingOrder (Qt::AscendingOrder),
  m_sortingColumn(0)
{
  m_messages = new SingleMsgsHistory;

  setRootItem(createRootItem());

  init();
}

SingleMsgsHistoryModel::~SingleMsgsHistoryModel()
{
}

TreeItem* SingleMsgsHistoryModel::createRootItem()
{
  QList<QVariant> data;
  data.append(tr("Direction / IP - Nickname / Date"));
  data.append(tr("IP"));
  data.append(tr("Nickname"));
  data.append(tr("Message"));

  TreeItem* item = new MessageTreeItem(data);

  return item;
}

void SingleMsgsHistoryModel::addMessage(SingleMessage* msg)
{
  QList<QVariant>  data;
  QString          user            = QHostAddress(msg->srcIp()).toString() + " - " + msg->userName();
  QString          second_lvl_id   = user + (msg->isIncoming() ? "-in" : "-out");
  MessageTreeItem* second_lvl_item = NULL;
  MessageTreeItem* first_lvl_item  = (msg->isIncoming() ? m_incoming : m_outgoing);
  QDateTime        dt;

  dt.setTime_t(msg->receiveTime());

  emit layoutAboutToBeChanged();

  switch(m_currentLayout)
  {
    case Date :
      second_lvl_item = first_lvl_item;
      break;

    case IpUserDate :
      if(!m_secondLevelItems.contains(second_lvl_id))
      {
        data << user << "" << "" << "";
        second_lvl_item = new MessageTreeItem(data, first_lvl_item);
        m_secondLevelItems.insert(second_lvl_id, second_lvl_item);

        second_lvl_item->hideColumn(IpCol);
        second_lvl_item->hideColumn(NicknameCol);
      }
      else
        second_lvl_item = m_secondLevelItems[second_lvl_id];

      break;
  }

  // preparing item which will be represents a message
  int max_len = 1024;
  QString res_msg = msg->msg();

  res_msg.replace("\n", " ").left(max_len);

  if(res_msg.size() > max_len)
    res_msg += "...";

  data.clear();
  data.append(dt.toString("hh:mm:ss (dd.MM.yy)"));
  data.append(QHostAddress(msg->srcIp()).toString());
  data.append(msg->userName());
  data.append(res_msg);

  MessageTreeItem* msg_item = new MessageTreeItem(data, second_lvl_item);

  m_messages->addMessage(msg);
  msg_item  ->setMessage(msg);

  data.clear();
  data << dt.toString("hh:mm:ss (dd.MM.yy)") << "" << "" << msg->msg();

  msg_item->setData(data, Qt::ToolTipRole);

  if(m_currentLayout == IpUserDate)
  {
    msg_item->hideColumn(IpCol);
    msg_item->hideColumn(NicknameCol);
  }

  sort(m_sortingColumn, (Qt::SortOrder)m_sortingOrder);

  emit layoutChanged();
}

void SingleMsgsHistoryModel::init()
{

  QList<QVariant> data;
  data.append(tr("Incoming"));
  data.append(tr(""));
  data.append(tr(""));
  data.append(tr(""));

  m_incoming = new MessageTreeItem(data);

  data.clear();
  data.append(tr("Outgoing"));
  data.append(tr(""));
  data.append(tr(""));
  data.append(tr(""));

  m_outgoing = new MessageTreeItem(data);

  appendToRoot(m_incoming);
  appendToRoot(m_outgoing);

  rootItem()->hideColumn(IpCol);
  rootItem()->hideColumn(NicknameCol);
}

void SingleMsgsHistoryModel::rebuildTree(int layout)
{
  if(m_currentLayout == (TreeLayout)layout)
    return;

  QList<TreeItem*> items;

  items.append(m_incoming);
  items.append(m_outgoing);

  reset();

  switch((m_currentLayout = (TreeLayout)layout))
  {
    case Date :
    {
      rootItem()->setData(0, tr("Direction / Date"));

      foreach(TreeItem* top_lvl_item, items)
      {
        foreach(TreeItem* item, *top_lvl_item->children())
        {
          // checking is item represents message or not
          if(!static_cast<MessageTreeItem*>(item)->message())
          {
            foreach(TreeItem* msg_item, item->takeChildren())
            {
              Message* message = static_cast<MessageTreeItem*>(msg_item)->message();
              if(message)
                top_lvl_item->appendChild(msg_item);
              else
                delete msg_item;
            }

            top_lvl_item->deleteChild(item);
            m_secondLevelItems.remove(m_secondLevelItems.key(static_cast<MessageTreeItem*>(item)));
          }
        }
      }

      rootItem()->showColumn(IpCol);
      rootItem()->showColumn(NicknameCol);

      break;
    }

    case IpUserDate :
      rootItem()->setData(0, tr("Direction / IP - Nickname / Date"));

      foreach(TreeItem* top_lvl_item, items)
      {
        foreach(TreeItem* item, top_lvl_item->takeChildren())
        {
          Message* msg = static_cast<MessageTreeItem*>(item)->message();
          if(msg)
            appendIn3lvl(item);
          else
            top_lvl_item->deleteChild(item);
        }
      }

      rootItem()->hideColumn(IpCol);
      rootItem()->hideColumn(NicknameCol);

      break;
  }
}

void SingleMsgsHistoryModel::appendIn3lvl(TreeItem* item)
{
  Message* msg = static_cast<MessageTreeItem*>(item)->message();
  QHostAddress     addr(msg->srcIp());
  QString          user = addr.toString() + " - " + msg->userName();
  QString          second_lvl_id = user + (msg->isIncoming() ? "-in" : "-out");
  MessageTreeItem* second_lvl_item = NULL;
  MessageTreeItem* first_lvl_item = (msg->isIncoming() ? m_incoming : m_outgoing);
  QList<QVariant> data;

  if(msg)
  {
     if(!m_secondLevelItems.contains(second_lvl_id))
     {
       data.append(user);
       data.append("");
       data.append("");
       data.append("");
       second_lvl_item = new MessageTreeItem(data, first_lvl_item);
       m_secondLevelItems.insert(second_lvl_id, second_lvl_item);
     }
     else
     {
       second_lvl_item = m_secondLevelItems[second_lvl_id];
     }

     second_lvl_item->appendChild(item);
  }
}

void SingleMsgsHistoryModel::sort(int column, Qt::SortOrder order)
{
  emit layoutAboutToBeChanged();

  m_sortingColumn = column;
  m_sortingOrder  = order;

  m_incoming->sortChildren(rootItem()->realColumn(column), order);
  m_outgoing->sortChildren(rootItem()->realColumn(column), order);

  emit layoutChanged();
}
