/**********************************************************************
 *
 * IsisDb.cpp
 * 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.
 *
 *********************************************************************/

////////////////////////////////////////////////////////////
// ISISDB: Isis Master file methods
////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "IsisDb.h"
#include "XRFFile.h"



//-------------------------------------------------------------------------------- 
// IsisDb::IsisDb()
//
// Constructor, Makes an ISIS Data Base object that isn't connected to a Master 
// file, Cross Reference file and Fdt.
//-------------------------------------------------------------------------------
IsisDb::IsisDb()
{
	bReadOnly_ = false;
	try
	{
        mf_  = new MfFile;
	    xf_  = new XrfFile; 
	    fdt_ = new CFdt;
	}
	catch(std::bad_alloc)
	{
		throw CIsisDbException(ISIS_BAD_ALLOC, __FILE__, __LINE__);
	}
}
 
//////////////////////////////
 
IsisDb::~IsisDb( )
{
   delete mf_; delete xf_; delete fdt_;
}
 
 
//////////////////////////////
 
int IsisDb::CreateDb(const TCHAR *fname)
{
   name = fname;
   MkNames();
   int rc = ISIS_NO_ERROR;

   // We should not try to create a mf_ which already exist!
   if (CFileBase::Exists(mfname_))
   {
	   throw CIsisDbException(ISIS_MF_ALREADY_EXIST_ERROR, __FILE__, __LINE__);
   }
   else
   {
       try
	   {
           rc = mf_->CreateMf(mfname_, USERMST);   
           rc = xf_->CreateXrf(xrfname_);
           rc = fdt_->Load(fdtname_);
	   }
       catch(CIsisDbException)
	   {
    	   throw CIsisDbException(ISIS_MF_OPEN_ERROR, __FILE__, __LINE__);
	   }
   }
   
   return rc;
}
 
 
//////////////////////////////
 
void IsisDb::CloseDb()
{
   mf_->CloseMf();
   xf_->Close();
}
 
//////////////////////////////
 
void IsisDb::MkNames()
// Make file names
{
    const _TCHAR *s = name.c_str();
	_TCHAR *ps = new _TCHAR[_tcslen(s)+1];
	_tcscpy(ps, s);
	_TCHAR * tmp = _tcsrchr(ps, _T('.'));
	assert(tmp != NULL);
    // Terminate the string at the last dot 
    *tmp = _T('\0');

   _tcscpy(mfname_,ps);
   _tcscat(mfname_,_T(".mst"));
   _tcscpy(xrfname_,ps);
   _tcscat(xrfname_,_T(".xrf"));
   _tcscpy(fdtname_,ps);
   _tcscat(fdtname_,_T(".fdt"));
   _tcscpy(idxname_,ps);
   _tcscat(idxname_,_T(".idx"));
   delete[] ps;
}
 
//////////////////////////////
 
int IsisDb::OpenDb(const TCHAR *fname,  FileSystem::AccessMode mode
				                              /* = FileSystem::FILE_READWRITE */)
{
   name = fname;
   MkNames();
   int rc;
   try
   {
     // if (FileSystem::IsReadOnly(mfname_))
     //	   mode = FileSystem::FILE_READONLY;
       rc = mf_->OpenMf(mfname_, mode);
       rc = xf_->OpenXrf(xrfname_, mode);
       rc = fdt_->Load(fdtname_);
   }
   catch(CIsisDbException)
   {
	   throw CIsisDbException(ISIS_MF_OPEN_ERROR, __FILE__, __LINE__);
   }

   return rc;
}
 
//----------------------------------------------------------------------------------
// int  IsisDb::ReadDbRecord(mg_s_long mfn, MfRecord &m)
//
// This function reads Master File record with MFN "mfn" into m
//
// Returns the status of the record: 
// Active=0, LogicalyDeleted=1, PhysicalyDeleted=2, EndOfFile=-1, NewRecord = 3
//----------------------------------------------------------------------------------
int  IsisDb::ReadDbRecord(mg_s_long mfn, MfRecord &m)
{
   mg_s_long mfb;
   int mfp;
   int status;
   bool rc;

   try
   {
       status = xf_->GetMfp(mfn, mfb, mfp);
       if (status == Active || status == LogicalyDeleted)
	       if (!mf_->ReadMfRecord(mfb, mfp, m))
			   status = -1;    // Error in reading the record!
   }
   catch(CIsisDbException)
   {
	   throw CIsisDbException(ISIS_MF_OPEN_ERROR, __FILE__, __LINE__);
   }
   return status;
}
 
//--------------------------------------------------------------------------------
// void CreateDbRecord(MfRecord &m)
//
// Create a new record at the end of the master file. The Master file address is
// set into the pair mfb/mfp and the XRF file is updated.
//---------------------------------------------------------------------------------
 void IsisDb::CreateDbRecord(MfRecord &m)
{
 
}

//--------------------------------------------------------------------------------
// void CreateDbRecordWithMfn(MfRecord &m)
//
// Create a new record at the end of the master file. The Master file address is
// set into the pair mfb/mfp and the XRF file is updated.
//---------------------------------------------------------------------------------
 void IsisDb::CreateDbRecordWithMfn(MfRecord &m)
{
 
}

 
//----------------------------------------------------------------------------------
// void  UpdateDbRecord(MfRecord &m)
//
// Update of existing records. Whenever a record is updated, the system writes
// the record back to the master file. Where it is written depends on the status
// of the record when it was initially read.
//
//----------------------------------------------------------------------------------
 void  IsisDb::UpdateDbRecord(MfRecord &m)
{
}
//----------------------------------------------------------------------------------
// int  IsisDb::DeleteRecord(mg_s_long mfn)
//
// This function logically deletes a Master File record with MFN "mfn".
// On XRF, xrfmfb is negative and on MST, status is set to 1
//
// Returns true if successful 
//----------------------------------------------------------------------------------
bool  IsisDb::DeleteRecord(mg_s_long mfn)
{

   return false;
}

mg_s_long  IsisDb::GetNextActiveMfn(mg_s_long mfn /* = -1 */)
{
	if (mfn == -1)
		mfn = 1;
	else
		mfn++;
	mg_s_long  mfb;
	int  mfp;
	int iRet = xf_->GetMfp(mfn, mfb, mfp);
	while (iRet != Active && iRet != EndOfFile)
	{
		mfn++;
        iRet = xf_->GetMfp(mfn, mfb, mfp);
	}
	if (iRet == EndOfFile)
		return 0;
	else
		return mfn;
}
	
_TCHAR *IsisDb::GetIdxFileName()
{
	return idxname_;
}

