/***************************************************************************
 *   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 "msghistory.h"

#include <assert.h>

#include "message.h"

MsgHistory::MsgHistory() :
  m_msgsNum   (0),
  m_msgsMaxNum(1024),
  m_allocStep (1024)
{
  m_msgs = (Message**)malloc(m_msgsMaxNum * sizeof(Message*));
  assert(NULL != m_msgs);
}

MsgHistory::~MsgHistory()
{
  qDebug("[~MsgHistory]");
  for(uint i = 0; i < m_msgsNum; i++)
    delete m_msgs[i];

  free(m_msgs);
}

void MsgHistory::addMsg(Message* new_msg)
{
  if(++m_msgsNum == m_msgsMaxNum)
  {
    m_msgsMaxNum += m_allocStep;
    m_msgs = (Message**)realloc(m_msgs, m_msgsMaxNum * sizeof(Message*));
  }
  m_msgs[m_msgsNum - 1] = new_msg;
}

Message* MsgHistory::msg(qint32 n)
{
  if(n >= 0 && n < (qint32)m_msgsNum)
    return m_msgs[n];
  return NULL;
}

const QByteArray & MsgHistory::toByteArray(qint32 max_num) const
{
  int i;
  char buf[38];

  // format of array:
  // 2 m_version;
  // 2 m_type;
  // 8 m_srcIp;
  // 8 m_sendTime;
  // 8 m_receiveTime;
  // 4 m_color;
  // 4 m_msg.size()
  // 1 m_userName.size();
  // 1 m_compName.size();
  // _______________
  // 38
  // QString m_msg;
  // QString m_userName;
  // QString m_compName;
  // _______________
  // 38 + m_msg.size() + m_userName.size() + m_compName.size()

  m_allMsgs.clear();

  i = (max_num >= (int)m_msgsNum || max_num < 0 ? 0 : m_msgsNum - max_num - 1);

  for(; i < (int)m_msgsNum; i++)
  {
    catUS2str (buf     , m_msgs[i]->version());
    catUS2str (buf + 2 , m_msgs[i]->type());
    catULL2str(buf + 4 , m_msgs[i]->srcIp());
    catULL2str(buf + 12, m_msgs[i]->sendTime());
    catULL2str(buf + 20, m_msgs[i]->receiveTime());

    buf[28] = (uchar)m_msgs[i]->color().red();
    buf[29] = (uchar)m_msgs[i]->color().green();
    buf[30] = (uchar)m_msgs[i]->color().blue();
    buf[31] = (uchar)m_msgs[i]->color().alpha();

    catULL2str(buf + 32, m_msgs[i]->msg().toUtf8().size());

    buf[36] = (char)m_msgs[i]->userName().toUtf8().size();
    buf[37] = (char)m_msgs[i]->compName().toUtf8().size();

    m_allMsgs.append(QByteArray(buf, 38));

    m_allMsgs.append(m_msgs[i]->msg     ().toUtf8());
    m_allMsgs.append(m_msgs[i]->userName().toUtf8());
    m_allMsgs.append(m_msgs[i]->compName().toUtf8());
  }

  return m_allMsgs;
}

void MsgHistory::fromByteArray(const QByteArray & arr)
{
  Message* msg;
  uint size = arr.size();
  uint msgl;
  uint cnl;
  uint unl;

  char* data = (char * )arr.data();

  for(uint i = 0; i < size; )
  {
    msg = new Message;

    i += 38;
    if(i < size)
    {
      msg->setVersion    (str2US (data     ));
      msg->setType       (str2US (data + 2 ));
      msg->setSrcIp      (str2ULL(data + 4 ));
      msg->setSendTime   (str2ULL(data + 12));
      msg->setReceiveTime(str2ULL(data + 20));
      msg->setColor      (QColor((uchar)data[28], (uchar)data[29], (uchar)data[30], (uchar)data[31]));

      msgl = str2ULL(data + 32);
      unl  = data[36];
      cnl  = data[37];

      i += msgl + unl + cnl;
      if(i < size)
      {
        msg->setMsg     (QString().fromUtf8(data + 38             , msgl));
        msg->setUserName(QString().fromUtf8(data + 38 + msgl      , unl ));
        msg->setCompName(QString().fromUtf8(data + 38 + msgl + unl, cnl ));
        data += 38 + msgl + unl + cnl;

        msg->setRequested(true);
        addMsg(msg);
      }
      else
        break;
    }
  }
}
