//  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$
//  ------------------------------------------------------------------
//  FrontDoor Nodelist Indexing.
//  Derived from code kindly provided by Scott Dudley.
//  ------------------------------------------------------------------

#ifndef __gftnnlfd_h
#define __gftnnlfd_h


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

#include <gftnnl.h>


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

#if defined(GOLD_CANPACK)
    #pragma pack(1)
#endif

struct _FDHdr
{
    word rsvd1;
    byte rsvd2;
    word master_idx;
};


//  ------------------------------------------------------------------
//  The four-byte header at the beginning of each Btree block

struct _FDInf
{
    char nodes;
    word index;
    char rsvd[2];
};


//  ------------------------------------------------------------------
//  Layout of first record

struct _FDCtl
{
    _FDInf inf;
    _FDHdr hdr;
    char   stuff[246];
    byte   unknown;
    char   nl_ext[3];
};


//  ------------------------------------------------------------------
//  Masks for the nlofs member

const uint32_t IN_FDNODE  = 0x01000000UL;  // Data in FDNODE.FD
const uint32_t IN_FDNET   = 0x10000000UL;  // Data in FDNET.PVT
const uint32_t IN_FDPOINT = 0x20000000UL;  // Data in FDPOINT.PVT


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

struct _FDGdx
{
    dword nlofs;
    word  block_num;
};


//  ------------------------------------------------------------------
//  A FrontDoor USERLIST.FDX record

struct _FDUdx
{
    dword nlofs;                     // Index into raw nodelist.
    word  block_num;                 // Block number (used in index recs only)
    word  rsvd1;                     // Unknown
    byte  rsvd2;                     // Unknown - always '\x18'
    char  name[15];                  // Space-padded, uppercase
    byte  zone_hi;                   // MSB of zone
    byte  zone_lo;                   // LSB of zone
    byte  net_hi;                    // MSB of net
    byte  net_lo;                    // LSB of net
    byte  node_hi;                   // MSB of node
    byte  node_lo;                   // LSB of node
    byte  point_hi;                  // MSB of point
    byte  point_lo;                  // LSB of point
    byte  type;                      // See TYPE_XXX
};


//  ------------------------------------------------------------------
//  Structure of a B-Tree data block in USERLIST.FDX. This structure
//  is always 1061 bytes long, and the file length is always a
//  multiple of this

struct _FDUdb
{
    _FDInf inf;
    _FDUdx udx[32];
};


//  ------------------------------------------------------------------
//  A FrontDoor NODELIST.FDX record

struct _FDFdx
{
    dword nlofs;                     // Index into raw nodelist.
    word  block_num;                 // Block number (used in index recs only)
    word  rsvd1;                     // Unknown
    byte  rsvd2;                     // Unknown - always '\x0e'
    byte  zone_hi;                   // MSB of zone
    byte  zone_lo;                   // LSB of zone
    byte  net_hi;                    // MSB of net
    byte  net_lo;                    // LSB of net
    byte  node_hi;                   // MSB of node
    byte  node_lo;                   // LSB of node
    byte  point_hi;                  // MSB of point
    byte  point_lo;                  // LSB of point
    word  host_route;                // Net# for host routng, or 0 if none
    word  hub_route;                 // Hub# for hub routing, or 0 if none
    byte  type;                      // See TYPE_XXX
    byte  sentinel;                  // Always 0xFF
};


//  ------------------------------------------------------------------
//  Structure of a B-Tree data block in NODELIST.FDX. This structure
//  is always 741 bytes long, and the file length is always a multiple
//  of this

struct _FDFdb
{
    _FDInf inf;
    _FDFdx fdx[32];
};


//  ------------------------------------------------------------------
//  B-Tree common data block with union for convenience

struct _FDBlk
{
    _FDInf info;
    union
    {
        _FDUdx name[32];
        _FDFdx addr[32];
    } node;
};


//  ------------------------------------------------------------------
//  The private Nodelist Database (FDNODE.FDA) has the following record
//  format. Note that the char[] fields are in Pascal fashion. The first
//  byte is the length byte. The actual string starts at [1] and the
//  string is not NUL terminated.

// Status
#define ISZC        1
#define ISRC        2
#define ISNC        3
#define ISHUB       4
#define ISPVT       5
#define ISHOLD      6
#define ISDOWN      7
#define ISPOINT     9

// Capability flags
#define CMflag      0x00000002L
#define MOflag      0x00000004L
#define HSTflag     0x00000008L
#define H96flag     0x00000010L
#define PEPflag     0x00000020L
#define MAXflag     0x00000040L
#define XXflag      0x00000080L
#define XBflag      0x00000100L
#define XRflag      0x00000200L
#define XPflag      0x00000400L
#define XWflag      0x00000800L
#define MNPflag     0x00001000L
#define HST14flag   0x00002000L
#define V32flag     0x00004000L
#define V33flag     0x00008000L
#define V34flag     0x00010000L
#define V42flag     0x00020000L
#define XCflag      0x00040000L
#define XAflag      0x00080000L
#define V42bflag    0x00100000L
#define V32bflag    0x00200000L
#define HST16flag   0x00400000L
#define LOflag      0x00800000L
#define ZYXflag     0x01000000L
#define UISDNAflag  0x02000000L
#define UISDNBflag  0x04000000L
#define UISDNCflag  0x08000000L
#define FAXflag     0x10000000L

// MaxBaud field
#define ISBAUD300        2
#define ISBAUD1200       4
#define ISBAUD2400       5
#define ISBAUD4800       6
#define ISBAUD7200      10
#define ISBAUD9600       7
#define ISBAUD12000     11
#define ISBAUD14400     12
#define ISBAUD16800     13
#define ISBAUD19200     14
#define ISBAUD38400     15
#define ISBAUD57600     16
#define ISBAUD64000     17
#define ISBAUD76800     18
#define ISBAUD115200    19

// Record structure
struct _FDFdn
{
    long erased;            // Used to signal erased status
    byte status;            // Zone, host, hub, etc.
    word node;              // Network address
    word net;               //
    word zone;              //
    word point;             //
    word routnode;          // Default routing within zone
    word routnet;           //
    word cost;              // Cost per minute for system
    long capability;        // Capability flags
    byte maxbaud;           // Maximum baud rate
    char name[31];          // Name of system
    char telephone[41];     // Raw telephone number
    char location[41];      // Location of system
    char user[37];          // SysOp name
    char selecttag[4];      // Group field
};


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

struct _FDStk
{
    uint blockno;
    uint block_num;
    int  maxnodes;
    int  node;
};


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

struct _FDstate
{
    uint   depth;
    _FDStk stack[8];
    int    blockno;
    int    node;
};

#if defined(GOLD_CANPACK)
    #pragma pack()
#endif


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

class ftn_frontdoor_nodelist_index : public ftn_nodelist_index_base
{

    bool          is_intermail;

    int           fdfd;
    int           nfd;
    int           pfd;
    int           ppfd;
    int           ufd;
    int           xfd;

    _FDCtl        ctl;

    _FDBlk        block;
    uint          blocksize;
    uint          blockno;
    uint          maxblockno;
    uint          lastblockno;
    int           node;

    _FDStk        stack[8];
    uint          depth;

    _FDstate      state;

    char          nodelist[13];
    long          nodelistoffset;

    char          searchname[16];
    ftn_addr      searchaddr;

    const _FDUdx& namerec() const;
    const _FDFdx& addrrec() const;
    const _FDGdx& noderec() const;
    void          getaddr(ftn_addr& addr) const;
    void          getblock();
    int           namecmp() const;
    int           addrcmp() const;
    void          getstatus(char* status, int type) const;
    void          fetchdata();
    void          getnodedata();
    void          push();
    void          pop();
    bool          prevnode();
    bool          nextnode();
    void          compare()
    {
        exactmatch = not (namebrowse ? namecmp() : addrcmp());
    }
    bool          search();

#ifdef DEBUG
    void          printnode() const;
#endif

public:

    ftn_frontdoor_nodelist_index();
    virtual ~ftn_frontdoor_nodelist_index();

    bool can_browse_name() const
    {
        return true;
    }
    bool can_browse_address() const
    {
        return true;
    }

    bool open();
    void close();

    bool find(const char* name);
    bool find(const ftn_addr& addr);

    bool previous();
    bool next();

    void first();
    void last();

    void push_state();
    void pop_state();

    const char* index_name() const;
    const char* nodelist_name() const;

};


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

#endif

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