/***************************************************************************
                          mimeheader.h  -  description
                             -------------------
    begin                : Fri Oct 20 2000
    copyright            : (C) 2000 by Sven Carstens
    email                : s.carstens@gmx.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef MIMEHEADER_H
#define MIMEHEADER_H

#include <QList>
#include <QHash>
#include <QByteArray>

#include "mimehdrline.h"
#include "mimeio.h"

#include <kimap/rfccodecs.h>
using namespace KIMAP;

/**
  *@author Sven Carstens
  */

class mimeHeader
{
public:
  mimeHeader ();
  virtual ~ mimeHeader ();

  virtual void addHdrLine (mimeHdrLine *);
  virtual void outputHeader (mimeIO &);
  virtual void outputPart (mimeIO &);


  QByteArray outputParameter (QHash < QString, QString > &);

//  int parsePart (mimeIO &, const QString&);
//  int parseBody (mimeIO &, QByteArray &, const QString&, bool mbox = false);

  // parse a header. returns true if it had a leading 'From ' line
  bool parseHeader (mimeIO &);

  QString getDispositionParm (const QByteArray&);
  void setDispositionParm (const QByteArray&, const QString&);
  QHashIterator < QString, QString > getDispositionIterator ();

  QString getTypeParm (const QByteArray&);
  void setTypeParm (const QByteArray&, const QString&);
  QHashIterator < QString, QString > getTypeIterator ();

  // recursively serialize all important contents to the QDataStream
  void serialize(QDataStream& stream);

  const QByteArray& getType ()
  {
    return _contentType;
  }
  void setType (const QByteArray& _str)
  {
    _contentType = _str;
  }

  const QByteArray& getDescription ()
  {
    return _contentDescription;
  }
  void setDescription( const QByteArray& _str )
  {
    _contentDescription = _str;
  }

  const QByteArray& getDisposition ()
  {
    return _contentDisposition;
  }
  void setDisposition( const QByteArray& _str )
  {
    _contentDisposition = _str;
  }

  const QByteArray& getEncoding ()
  {
    return _contentEncoding;
  }
  void setEncoding (const QByteArray &_str )
  {
    _contentEncoding = _str;
  }

  const QByteArray& getMD5 ()
  {
    return _contentMD5;
  }
  void setMD5 (const QByteArray & _str)
  {
    _contentMD5 = _str;
  }

  const QByteArray& getID ()
  {
    return _contentID;
  }
  void setID (const QByteArray & _str)
  {
    _contentID = _str;
  }

  unsigned long getLength ()
  {
    return contentLength;
  }
  void setLength (unsigned long _len)
  {
    contentLength = _len;
  }

  const QString & getPartSpecifier ()
  {
    return partSpecifier;
  }
  void setPartSpecifier (const QString & _str)
  {
    partSpecifier = _str;
  }

  QListIterator < mimeHdrLine *> getOriginalIterator ();
  QListIterator < mimeHdrLine *> getAdditionalIterator ();
  void setContent (const QByteArray &aContent)
  {
    mimeContent = aContent;
  }
  QByteArray getContent ()
  {
    return mimeContent;
  }

  QByteArray getBody ()
  {
    return preMultipartBody + postMultipartBody;
  }
  QByteArray getPreBody ()
  {
    return preMultipartBody;
  }
  void setPreBody (QByteArray & inBody)
  {
    preMultipartBody = inBody;
  }

  QByteArray getPostBody ()
  {
    return postMultipartBody;
  }
  void setPostBody (QByteArray & inBody)
  {
    postMultipartBody = inBody;
    contentLength = inBody.length ();
  }

  mimeHeader *getNestedMessage ()
  {
    return nestedMessage;
  }
  void setNestedMessage (mimeHeader * inPart, bool destroy = true)
  {
    if (nestedMessage && destroy)
      delete nestedMessage;
    nestedMessage = inPart;
  }

//  mimeHeader *getNestedPart() { return nestedPart; };
  void addNestedPart (mimeHeader * inPart)
  {
    nestedParts.append (inPart);
  }
  QListIterator < mimeHeader *> getNestedIterator ()
  {
    return QListIterator < mimeHeader *> (nestedParts);
  }

  // clears all parts and deletes them from memory
  void clearNestedParts ()
  {
    nestedParts.clear ();
  }

  // clear all parameters to content-type
  void clearTypeParameters ()
  {
    typeList.clear ();
  }

  // clear all parameters to content-disposition
  void clearDispositionParameters ()
  {
    dispositionList.clear ();
  }

  // return the specified body part or NULL
  mimeHeader *bodyPart (const QString &);

#ifdef KMAIL_COMPATIBLE
  ulong msgSize ()
  {
    return contentLength;
  }
  uint numBodyParts ()
  {
    return nestedParts.count ();
  }
  mimeHeader *bodyPart (int which, mimeHeader ** ret = NULL)
  {
    if (ret)
      (*ret) = nestedParts.at (which);
    return nestedParts.at (which);
  }
  void write (const QString &)
  {
  }
  QString typeStr ()
  {
    return QString (contentType.left (contentType.find ('/')));
  }
  void setTypeStr (const QString & _str)
  {
    contentType = QByteArray (_str.toLatin1 ()) + "/" + subtypeStr ().toLatin1 ();
  }
  QString subtypeStr ()
  {
    return QString (contentType.
                    right (contentType.length () - contentType.find ('/') -
                           1));
  }
  void setSubtypeStr (const QString & _str)
  {
    contentType = QByteArray (typeStr ().toLatin1 ()) + "/" + _str.toLatin1 ();
  }
  QString cteStr ()
  {
    return QString (getEncoding ());
  }
  void setCteStr (const QString & _str)
  {
    setEncoding (_str.toLatin1 ());
  }
  QString contentDisposition ()
  {
    return QString (_contentDisposition);
  }
  QString body ()
  {
    return QString (postMultipartBody);
  }
  QString charset ()
  {
    return getTypeParm ("charset");
  }
  QString bodyDecoded ();
  void setBodyEncoded (const QByteArray &);
  void setBodyEncodedBinary (const QByteArray &);
  QByteArray bodyDecodedBinary ();
  QString name ()
  {
    return QString (getTypeParm ("name"));
  }
  void setName (const QString & _str)
  {
    setTypeParm ("name", _str);
  }
  QString fileName ()
  {
    return QString (getDispositionParm ("filename"));
  }
  QString contentDescription ()
  {
    return QString (RfcCodecs::decodeRFC2047String (_contentDescription));
  }
  void setContentDescription (const QString & _str)
  {
    _contentDescription = RfcCodecs::encodeRFC2047String (_str).toLatin1 ();
  }
  QString msgIdMD5 ()
  {
    return QString (contentMD5);
  }
  QString iconName ();
  QString magicSetType (bool aAutoDecode = true);
  QString headerAsString ();
  ulong size ()
  {
    return 0;
  }
  void fromString (const QByteArray &)
  {;
  }
  void setContentDisposition (const QString & _str)
  {
    setDisposition (_str.toLatin1 ());
  }
#endif

protected:
  static void addParameter (const QByteArray&, QHash < QString, QString > &);
  static QString getParameter (const QByteArray&, QHash < QString, QString > &);
  static void setParameter (const QByteArray&, const QString&, QHash < QString, QString > &);

  QList < mimeHdrLine *> originalHdrLines;

private:
  QList < mimeHdrLine *> additionalHdrLines;
  QHash < QString, QString > typeList;
  QHash < QString, QString > dispositionList;
  QByteArray _contentType;
  QByteArray _contentDisposition;
  QByteArray _contentEncoding;
  QByteArray _contentDescription;
  QByteArray _contentID;
  QByteArray _contentMD5;
  unsigned int contentLength;
  QByteArray mimeContent;
  QByteArray preMultipartBody;
  QByteArray postMultipartBody;
  mimeHeader *nestedMessage;
  QList < mimeHeader *> nestedParts;
  QString partSpecifier;

};

#endif
