//  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$
//  ------------------------------------------------------------------
//  Area structures and classes.
//  ------------------------------------------------------------------


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

#ifndef __GMBAREA_H
#define __GMBAREA_H


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

#include <string>
#include <gutltag.h>
#include <glog.h>
#include <gedacfg.h>
#include <gmo_msg.h>


//  ------------------------------------------------------------------
//  Area base class

class gmo_area
{
public:

    //  ----------------------------------------------------------------
    //  Constructor and destructor

    gmo_area();
    virtual ~gmo_area();


    //  ----------------------------------------------------------------
    //  Data members

    GTag*   Msgn;               // Message numbers
    GTag*   PMrk;               // Personal mail marks

    uint    lastread;           // Number of last message read
    uint32_t   lastreadentry;      // Lastread message number at entry to area

    int     isopen;             // NONZERO if open

protected:
    //  ----------------------------------------------------------------
    //  Config data

    AreaCfgBase cfg;

private:
    std::string sEchoid;
    std::string sDesc;
    std::string sPath;

public:

    //  ----------------------------------------------------------------
    //  Access config data

    int   areaid() const
    {
        return cfg.areaid;
    }
    int   groupid() const
    {
        return cfg.groupid;
    }
    uint  type() const
    {
        return cfg.type;
    }
    const std::string &basetype() const
    {
        return cfg.basetype;
    }
    uint  board() const
    {
        return cfg.board;
    }
    const ftn_addr& aka() const
    {
        return cfg.aka;
    }
    int   originno() const
    {
        return cfg.originno;
    }
    Attr& attr()
    {
        return cfg.attr;
    }
    bool  ispacked() const
    {
        return make_bool(cfg.attr.pkd());
    }
    void  packed(bool a)
    {
        cfg.attr.pkd(a);
    }

    bool ascan()
    {
        return (bool)cfg.scan;
    }
    bool ascanexcl()
    {
        return (bool)cfg.scanexcl;
    }
    bool ascanincl()
    {
        return (bool)cfg.scanincl;
    }
    bool pmscan()
    {
        return (bool)cfg.pmscan;
    }
    bool pmscanexcl()
    {
        return (bool)cfg.pmscanexcl;
    }
    bool pmscanincl()
    {
        return (bool)cfg.pmscanincl;
    }

    const char* echoid() const
    {
        return sEchoid.c_str();
    }
    const char* desc() const
    {
        return sDesc.c_str();
    }
    const char* path() const
    {
        return sPath.c_str();
    }

    void set_areaid(int a)
    {
        cfg.areaid = a;
    }
    void set_groupid(int g)
    {
        cfg.groupid = g;
    }
    void set_type(uint t)
    {
        cfg.type = t;
    }
    void set_basetype(const char *m)
    {
        cfg.basetype = m;
    }
    void set_basetype(const std::string &m)
    {
        cfg.basetype = m;
    }
    void set_board(uint b)
    {
        cfg.board = b;
    }
    void set_aka(ftn_addr& a)
    {
        cfg.aka = a;
    }
    void set_originno(int o)
    {
        cfg.originno = o;
    }
    void set_attr(Attr& a)
    {
        cfg.attr = a;
    }
    void set_origin(char* o)
    {
        std::string tmp = o;
        cfg.setorigin(tmp);
    }

    void set_scan(bool s)
    {
        cfg.scan = (byte)s;
    }
    void set_scanexcl(bool s)
    {
        cfg.scanexcl = (byte)s;
    }
    void set_scanincl(bool s)
    {
        cfg.scanincl = (byte)s;
    }
    void set_pmscan(bool s)
    {
        cfg.pmscan = (byte)s;
    }
    void set_pmscanexcl(bool s)
    {
        cfg.pmscanexcl = (byte)s;
    }
    void set_pmscanincl(bool s)
    {
        cfg.pmscanincl = (byte)s;
    }

    void set_echoid(const char* s)
    {
        sEchoid = s;
    }
    void set_desc(const char* s)
    {
        sDesc = s;
    }
    void set_path(const char* s)
    {
        sPath = s;
    }


    //  ----------------------------------------------------------------
    //  Determine msgbase format

    bool isseparator() const;


    //  ----------------------------------------------------------------
    //  Determine area features

    virtual bool issoftdelete() const
    {
        return false;
    }
    virtual bool havearrivedstamp() const
    {
        return true;
    }
    virtual bool havereceivedstamp() const
    {
        return true;
    }
    virtual bool requirehardterm() const
    {
        return false;
    }
    virtual bool requiresoftterm() const
    {
        return false;
    }


    //  ----------------------------------------------------------------
    //  Determine area type

    int isnet() const;
    int isecho() const;
    int islocal() const;
    int isemail() const;
    int isnewsgroup() const;
    int isinternet() const;
    int isqwk() const;
    int issoup() const;


    //  ----------------------------------------------------------------
    //  Low-level messagebase member functions

    virtual void open() = 0;
    virtual void close() = 0;

    virtual void suspend() = 0;
    virtual void resume() = 0;

    virtual void lock() = 0;
    virtual void unlock() = 0;

    virtual void scan() = 0;
    virtual void scan_area() = 0;
    virtual void scan_area_pm() = 0;

    virtual int load_hdr(gmsg* msg) = 0;
    virtual int load_msg(gmsg* msg) = 0;

    virtual void save_hdr(int mode, gmsg* msg) = 0;
    virtual void save_msg(int mode, gmsg* msg) = 0;

    virtual void del_msg(gmsg* msg) = 0;

    virtual void new_msgno(gmsg* msg) = 0;
    virtual char* user_lookup(char* lookfor) = 0;
    virtual int renumber() = 0;

    virtual void update_timesread(gmsg* msg) = 0;

    virtual Line* make_dump_msg(Line*& lin, gmsg* msg, char* lng_head) = 0;

    virtual void set_highwater_mark() { }
    virtual void reset_highwater_mark() { }

protected:
    Path realpath;
    const char* real_path() const
    {
        return ispacked() ? realpath : path();
    }
    void set_real_path(const char* newpath)
    {
        strxcpy(realpath, newpath, sizeof(Path));
    }
};


//  ------------------------------------------------------------------
//  Inline implementations

inline bool gmo_area::isseparator() const
{
    return cfg.isseparator();
}

inline int gmo_area::isnet() const
{
    return cfg.isnet();
}
inline int gmo_area::isecho() const
{
    return cfg.isecho();
}
inline int gmo_area::islocal() const
{
    return cfg.islocal();
}
inline int gmo_area::isemail() const
{
    return cfg.isemail();
}
inline int gmo_area::isnewsgroup() const
{
    return cfg.isnewsgroup();
}
inline int gmo_area::isinternet() const
{
    return cfg.isinternet();
}
inline int gmo_area::isqwk() const
{
    return cfg.isqwk();
}
inline int gmo_area::issoup() const
{
    return cfg.issoup();
}


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

class SepArea : public gmo_area
{

public:

    SepArea() { }
    virtual ~SepArea() { }

    //  ----------------------------------------------------------------
    //  Messagebase member functions

    void open() { }
    void close() { }

    void suspend() { }
    void resume() { }

    void lock() { }
    void unlock() { }

    void scan() { }
    void scan_area() { }
    void scan_area_pm() { }

    int load_hdr(gmsg*)
    {
        return 0;
    }
    int load_msg(gmsg*)
    {
        return 0;
    }

    void save_hdr(int, gmsg*) { }
    void save_msg(int, gmsg*) { }

    void del_msg(gmsg*) { }

    void new_msgno(gmsg*) { }
    char* user_lookup(char*)
    {
        return NULL;
    }
    int renumber()
    {
        return false;
    }

    void update_timesread(gmsg*) { }

    Line* make_dump_msg(Line*&, gmsg*, char*)
    {
        return NULL;
    }
};


//  ------------------------------------------------------------------
//  Personal mail

const int PM_STARTUP  = 0x0001;
const int PM_ALLNAMES = 0x0002;
const int PM_LISTONLY = 0x0004;


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

extern glog*        WideLog;
extern int          WideDebug;
extern int          WideCanLock;
extern const char** WideUsername;
extern int          WideUsernames;
extern uint         WideSharemode;
extern bool         WideDispsoftcr;  // DispsoftCR for current area
extern int          WidePersonalmail;

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

bool PopupLocked(long __tries, int __isopen, const char* __file);
const char* Unpack(const char* archive);
void CleanUnpacked(const char* unpacked);

//  ------------------------------------------------------------------
//  SOFTCR management

// Detects SoftCR only if DispsoftCR is ON
inline bool issoftcr(char c)
{
    return not WideDispsoftcr and (c == SOFTCR);
}

//  Skip spaces and SoftCRs (if DispsoftCR is ON)
inline char *spanspaces(const char *str)
{
    while ( (isspace(*str) and (*str != CR)) or issoftcr(*str) )
        str++;
    return (char *)str;
}

// Skip LineFeeds and SoftCRs (if DispsoftCR is ON)
inline char *spanfeeds(const char *str)
{
    while ( (*str == LF) or issoftcr(*str) )
        str++;
    return (char *)str;
}


#endif

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

