//  This may look like C code, but it is really -*- C++ -*-

//  ------------------------------------------------------------------
//  The Goldware Library
//  Copyright (C) 1990-1999 Odinn Sorensen
//  Copyright (C) 1999-2000 Alexander S. Aganichev
//  ------------------------------------------------------------------
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Library General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library 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
//  Library General Public License for more details.
//
//  You should have received a copy of the GNU Library General Public
//  License along with this program; if not, write to the Free
//  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
//  MA 02111-1307, USA
//  ------------------------------------------------------------------
//  $Id$
//  ------------------------------------------------------------------
//  Message structures and classes.
//  ------------------------------------------------------------------


//  ------------------------------------------------------------------

#ifndef __GMB_MSG_H
#define __GMB_MSG_H


//  ------------------------------------------------------------------

#include <gftnall.h>
#include <gtimall.h>
#include <gvidall.h>
#include <gmsgattr.h>
#include <gmemdbg.h>

#include <vector>


//  ------------------------------------------------------------------
//  Internet name typedefs

typedef char INam[128];


//  ------------------------------------------------------------------
//  Internet subject typedefs

typedef char ISub[1301];


//  ------------------------------------------------------------------
//  Message modes

const uint GMSG_HDR         = 0x0001;
const uint GMSG_TXT         = 0x0002;
const uint GMSG_HDRTXT      = 0x0003;  // GMSG_HDR|GMSG_TXT
const uint GMSG_NEW         = 0x0010;
const uint GMSG_UPDATE      = 0x0020;
const uint GMSG_DELETE      = 0x0040;
const uint GMSG_COPY        = 0x0080;
const uint GMSG_MOVE        = 0x0100;
const uint GMSG_UNS_NOT_RCV = 0x0200;
const uint GMSG_NOLSTUPD    = 0x8000;


//  ------------------------------------------------------------------
//  Line attributes

const uint GLINE_TEAR = 0x0001;
const uint GLINE_ORIG = 0x0002;
const uint GLINE_HIDD = 0x0004;
const uint GLINE_KLUD = 0x0008;
const uint GLINE_QUOT = 0x0010;
const uint GLINE_HARD = 0x0020;
const uint GLINE_WRAP = 0x0040;
const uint GLINE_BLOK = 0x0080;
const uint GLINE_POSI = 0x0100;
const uint GLINE_HIGH = 0x0200;
const uint GLINE_TAGL = 0x0400;
const uint GLINE_SIGN = 0x0800;
const uint GLINE_TXTH = 0x1000;  // text is hiden
const uint GLINE_NOAL = 0x2000;  // text is not allocated

const uint GLINE_KLUDGE = GLINE_HIDD | GLINE_KLUD;
const uint GLINE_ALL    = GLINE_HIDD | GLINE_KLUD | GLINE_QUOT;


//  ------------------------------------------------------------------
//  Kludge types

const uint GKLUD_INTL      = 0x0001;
const uint GKLUD_FMPT      = 0x0002;
const uint GKLUD_TOPT      = 0x0004;
const uint GKLUD_FLAGS     = 0x0008;
const uint GKLUD_AREA      = 0x0010;
const uint GKLUD_MSGID     = 0x0020;
const uint GKLUD_REPLY     = 0x0040;
const uint GKLUD_PID       = 0x0080;
const uint GKLUD_FWD       = 0x0100;
const uint GKLUD_PATH      = 0x0200;
const uint GKLUD_SEENBY    = 0x0400;
const uint GKLUD_CHARSET   = 0x0800;
const uint GKLUD_REPLYTO   = 0x1000;
const uint GKLUD_REPLYADDR = 0x2000;
const uint GKLUD_KNOWN     = 0x4000;
const uint GKLUD_RFC       = 0x8000;


//  ------------------------------------------------------------------
//  Search locations

const uint GFIND_FROM      = 0x0001;
const uint GFIND_TO        = 0x0002;
const uint GFIND_SUBJECT   = 0x0004;
const uint GFIND_BODY      = 0x0008;
const uint GFIND_TAGLINE   = 0x0010;
const uint GFIND_TEARLINE  = 0x0020;
const uint GFIND_ORIGIN    = 0x0040;
const uint GFIND_KLUDGES   = 0x0080;
const uint GFIND_SIGNATURE = 0x0100;
const uint GFIND_HDR       = GFIND_FROM | GFIND_TO | GFIND_SUBJECT;
const uint GFIND_HDRTXT    = GFIND_HDR | GFIND_BODY;


//  ------------------------------------------------------------------
//  Charset encoding formats

const int GCHENC_CMP = 0x0001;    // Composed characters
const int GCHENC_I51 = 0x0002;    // FSC-51
const int GCHENC_MNE = 0x0004;    // K.Simonsen Mnemonic
const int GCHENC_QP  = 0x0008;    // Quoted-Printable


//  ------------------------------------------------------------------
//  Line record

class Line
{

public:

    vattr color;            // Line color
    uint  type;             // GLINE_*
    uint  kludge;           // GKLUD_*
    std::string txt;             // The line text
    Line* prev;             // Pointer to previous line
    Line* next;             // Pointer to next line

    Line() : txt ("")
    {
        color = BLACK_|_BLACK;
        type = kludge = 0;
        prev = next = NULL;
    }
    Line(const char *str) : txt (str)
    {
        color = BLACK_|_BLACK;
        type = kludge = 0;
        prev = next = NULL;
    }
    ~Line()              {}

    int  istearline()
    {
        return !!(type & GLINE_TEAR);
    }
    int  isorigin()
    {
        return !!(type & GLINE_ORIG);
    }
    int  ishidden()
    {
        return !!(type & GLINE_HIDD);
    }
    int  iskludge()
    {
        return !!(type & GLINE_KLUD);
    }
    int  isquote()
    {
        return !!(type & GLINE_QUOT);
    }
    int  ishard()
    {
        return !!(type & GLINE_HARD);
    }
    int  iswrapped()
    {
        return !!(type & GLINE_WRAP);
    }
    int  isblock()
    {
        return !!(type & GLINE_BLOK);
    }
    int  isposition()
    {
        return !!(type & GLINE_POSI);
    }
    int  ishighlighted()
    {
        return !!(type & GLINE_HIGH);
    }
    int  istagline()
    {
        return !!(type & GLINE_TAGL);
    }
    int  istxthidden()
    {
        return !!(type & GLINE_TXTH);
    }
    int  isheader()
    {
        return !!kludge;
    }

    int  isallocated()
    {
        return !(type & GLINE_NOAL);
    }
};


//  ------------------------------------------------------------------

Line* AddLineF(Line*& line, const char* format, ...) __attribute__ ((format (printf, 2, 3)));
Line* AddLine(Line* line, const char* buf);
Line* AddHexdump(Line*& line, void* data, size_t datalen);


//  ------------------------------------------------------------------

class gmsg_links
{
private:
    uint32_t reply_to;
    uint32_t reply_first;
    uint32_t reply_next;

    std::vector<uint32_t> reply_list;

public:

    gmsg_links()
        : reply_to(0)
        , reply_first(0)
        , reply_next(0)
    {
    }

    void reset()
    {
        reply_to = reply_first = reply_next = 0;
        reply_list.clear();
    }

    int list_max() const
    {
        return reply_list.size();
    }

    void to_set(uint32_t m)
    {
        reply_to = m;
    }
    void first_set(uint32_t m)
    {
        reply_first = m;
    }
    void next_set(uint32_t m)
    {
        reply_next = m;
    }

    void list_set(size_t n, uint32_t m)
    {
        size_t size = reply_list.size();
        if (n >= size)
        {
            for (size_t i = size; i <= n; i++)
                reply_list.push_back(0);
        }

        reply_list[n] = m;
    }

    uint32_t to() const
    {
        return reply_to;
    }
    uint32_t first() const
    {
        return reply_first;
    }
    uint32_t next() const
    {
        return reply_next;
    }

    uint32_t list(size_t n) const
    {
        if (n >= reply_list.size())
            return 0;

        return reply_list[n];
    }

};


//  ------------------------------------------------------------------

struct gmsg_jam_fields
{

    int32_t subfieldlen;   // Size of subfields
};


//  ------------------------------------------------------------------

struct gmsg_pcboard_fields
{

    char status;          // Msg header status byte
    byte exthdrflags;     // Msg extended header flags
    char password[13];    // Password needed to read the message
    time32_t reply_written;   // Timestamp of the original
};


//  ------------------------------------------------------------------

struct gmsg_wildcat_fields
{

    char  from_title[11];
    int32_t  from_userid;
    char  to_title[11];
    int32_t  to_userid;
    char  network[9];
    char  internal_attach[13];
    char  external_attach[13];
    uint32_t next_unread;
    uint32_t prev_unread;
    char  reserved[20];
};


//  ------------------------------------------------------------------

struct gmsg_adeptxbbs_fields
{

    uint32_t iflags;       // Internet related flags
    uint32_t oflags;       // Other network related flags
};


//  ------------------------------------------------------------------

struct gmsg_ezycom_fields
{

    byte extattr;
};


//  ------------------------------------------------------------------
//  Base class

class gmsg
{

public:

    uint        board;            // Board number (if applicable)

    uint32_t    msgno;            // Message number
    gmsg_links  link;             // Message reply links

    ftn_addr    oorig;            // Original origination address
    ftn_addr    orig;             // Origination address
    ftn_domain  odom;             // Originating domain

    ftn_addr    odest;            // Original destination address
    ftn_addr    dest;             // Destination address
    ftn_domain  ddom;             // Destination domain

    INam        by;               // Who from
    INam        to;               // Who to
    ISub        re;               // Subject

    time32_t      written;          // Timestamp
    time32_t      arrived;          // Timestamp
    time32_t      received;         // Timestamp

    Attr        attr;             // Message attributes
    uint        cost;             // Cost of msg if Netmail
    uint        timesread;        // Number of times read

    ftn_addr    msgid;            // MSGID kludge address
    char        msgids[201];      // MSGID kludge string
    char        replys[201];      // REPLY kludge string

    char        pid[80];          // PID kludge string

    int32_t        txtstart;         // Text starting position or record
    int32_t        txtlength;        // Text length or number of records
    uint        txtblocks;        // Number of msg text blocks

    char*       txt;              // Message text

    gmsg_jam_fields       jam;
    gmsg_pcboard_fields   pcboard;
    gmsg_wildcat_fields   wildcat;
    gmsg_adeptxbbs_fields adeptxbbs;
    gmsg_ezycom_fields    ezycom;

    gmsg()
        : board(0)
        , msgno(0)
        , link()
        , oorig()
        , orig()
        , odom()
        , odest()
        , dest()
        , ddom()
        , written(0)
        , arrived(0)
        , received(0)
        , attr()
        , cost(0)
        , timesread(0)
        , msgid()
        , txt(NULL)
    {
        by[0] = 0;
        to[0] = 0;
        re[0] = 0;
        msgids[0] = 0;
        replys[0] = 0;
        pid[0] = 0;
        memset(&jam, 0, sizeof(jam));
        memset(&pcboard, 0, sizeof(pcboard));
        memset(&wildcat, 0, sizeof(wildcat));
        memset(&adeptxbbs, 0, sizeof(adeptxbbs));
        memset(&ezycom, 0, sizeof(ezycom));
    }

    void reset()
    {
        board = 0;
        msgno = 0;
        link.reset();
        oorig.reset();
        orig.reset();
        odom[0] = 0;
        odest.reset();
        dest.reset();
        ddom[0] = 0;
        by[0] = 0;
        to[0] = 0;
        re[0] = 0;
        written = 0;
        arrived = 0;
        received = 0;
        attr.reset();
        cost = 0;
        timesread = 0;
        msgid.reset();
        msgids[0] = 0;
        replys[0] = 0;
        pid[0] = 0;
        txtstart = 0;
        txtlength = 0;
        txtblocks = 0;
        throw_xrelease(txt);
        memset(&jam, 0, sizeof(jam));
        memset(&pcboard, 0, sizeof(pcboard));
        memset(&wildcat, 0, sizeof(wildcat));
        memset(&adeptxbbs, 0, sizeof(adeptxbbs));
        memset(&ezycom, 0, sizeof(ezycom));
    }
};


//  ------------------------------------------------------------------

#endif

//  ------------------------------------------------------------------

