/**********************************************************************
 *
 * Fdt.h
 * Copyright (C) 2003  UNESCO
 *
 * A component of the Greenstone digital library software
 * from the New Zealand Digital Library Project at the
 * University of Waikato, New Zealand.
 *
 * 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.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *********************************************************************/

////////////////////////////////////////////////////////////////////////////////////
// Fdt.h

#ifndef __FDT_H__
#define __FDT_H__

#include <vector>
#include "mytchar.h"

#define FDT_NAME_LENG    30     // maximum name length in FDT_FILE
#define FDT_SFLD_LENG    20    // maximum subfield length in FDT_FILE

#ifndef __CFIELDDEF__
#define __CFIELDDEF__

class CFieldDef
{
public:
	enum FieldType {
		charField       = 'C',
		dateField       = 'D',
		numericField    = 'N',
		logicalField    = 'L',
		memoField       = 'M'
	};

	char  name[31];   // dbf field names are 10 chars long max.
		// If this application is compiled with _UNICODE switch,
		// the field name will be converted to wide chars
		// when the column header is displayed in the grid.
	char  type;
	short len;
	short width;
	short decimals;
	int   offset;
	short display_width;
};
#endif // __CFIELDDEF__



class CFdtEntry
{
public:
	CFdtEntry() :  tag(0), len(0), type(0), rep(0) 
	{ name[0] = '\0'; subfields[0] = '\0'; }
    void Clear()
	{
		tag = len = type = rep = 0;
        name[0] = '\0'; subfields[0] = '\0';
	}
    char    name[FDT_NAME_LENG+1];
    char    subfields[FDT_SFLD_LENG+1];
    int      tag;
    int      len;
    int      type;     //X=0
    int      rep;      //repeatable 1, non rep. 0
   CFdtEntry& operator=(const CFdtEntry& rhs)
   {
	   if (&name[0] != &rhs.name[0])
	   {
		   Copy(rhs);
	   }
	   return *this;
   }

   void Copy(const CFdtEntry &rhs)
   {
	   strcpy(name, rhs.name);
	   strcpy(subfields, rhs.subfields);
	   tag  = rhs.tag;
	   len  = rhs.len;
	   type = rhs.type;
	   rep  = rhs.rep;
   }
};


void FormatFdtEntry(CFdtEntry &e, ustring &s);



class CFdt
{
protected:
	std::vector<CFdtEntry>  m_aFdt;
    int                     m_nFieldCount;       // Num. of fields
	std::vector<CFieldDef*> m_fieldArray;        // Array with fields

	mg_s_long        m_iCurrentRecord;    // Current read record stored in
	CFdtEntry   m_fdtEntry;
	bool        m_bReadOnly;
	bool        m_bIsEmpty;
	bool        m_bDirty;            // True if m_fdtEntry modified 
	bool        m_bAppend;
public:
	ustring  m_sFileName;              // Fdt full pathname
	std::vector<std::string> m_asPrelude;  // What is bef ***
public:
	CFdt();          
	virtual ~CFdt();

	bool      Load(const _TCHAR *fname);
	int       GetEntryCount() { return m_aFdt.size(); }

	CFdtEntry GetEntryAt(int i) 
	{ 
      #ifdef _MSC_VER
	     return m_aFdt.at(i); 
      #else
	     return m_aFdt[i];
      #endif
	}

	int       GetFieldCount() { return  m_nFieldCount; }

    bool      Open(const char* szFileName, bool readOnly=true);

    void InitData();

    void Close();
 
    void DeleteContents();

    void Store(const char* fileName);
    int InitFields ();

    CFieldDef* GetField(int n) const;

    CFdtEntry GetAt(int i);

    const CFdtEntry GetAt(int i) const;

    int Append(CFdtEntry& e);

    void RemoveAt(int i);
    void SetAt(int i, CFdtEntry& e);

    bool Seek(mg_s_long iRecord);
    void Flush();
    bool GetValue(int n, std::string& result);
    bool SetValue(int n, const char* pszValue);

	int GetRecordCount() { return m_aFdt.size(); }
};

#endif
