/*
 *  db.cpp
 *  (C) gsd 2001
 */

// #include <sstream>      // for standard
#include <strstream>    // for g++
#include <string>
#include <iostream>
#include <fstream>
#include <cstdlib>

#include "db.h"

using namespace std;

CDataBase::CDataBase( string fname) : ifile(&fb), ofile(&fb)
{
    if ( fb.open( fname.c_str(), ios::in | ios::out) )
    {
        
    }
    else
    {
        cerr << "Can't open " << fname << endl;
        exit(1);
    }
}
void CDataBase::receive( long sender, string message)
{
//    istringstream is( message);       // for standard
    istrstream  is(message.c_str());    // for g++
    string  command;    

    if ( is >> command )
    {
        if ( "REG" == command )
        {
            string  uid, number;
            if( is >> uid >> number )
                if ( store( uid, uid+" "+number) )
                    send( sender, uid + ", " + number + " registered" );
        }
        else if ( "UNREG" == command )
        {
            string  uid;
            if ( is >> uid )
                if ( remove( uid) )
                    send( sender, uid + " unregistered" );
        }
        else if ( "LOAD" == command )
        {
            string  uid;
            string  s;
            is >> uid;
            if ( retrieve( uid, s) )
                send( sender, s);
        }
        else if ( "LREG" == command )
        {
            fb.pubseekoff(0, ios::beg);
            string s;
            while ( getline( ifile, s) )
            {
                if ( s.find("DELETED") )
                    send( sender, s);
            }
            send( sender, "==== ENDFILE ====");
            ifile.clear();
        }
        else
            send( sender, "DB: bad command");
    }
    else
        send( sender, "DB: bad parameters");
}
bool CDataBase::find( std::string uid, streampos &rpos)
{
    string      s;
    streampos   spos = 0;

    fb.pubseekoff( 0, ios::beg);
    while ( getline( ifile, s) )
    {
//      istringstream   is(s);  // for strandard
        istrstream  is(s.c_str());
        string      skey;

        if ( is >> skey  &&  skey == uid )
        {
            rpos = spos;
            return true;
        }
        spos = fb.pubseekoff( 0, ios::cur);
    }
    ifile.clear();  // clear eof_bit
    return false;
}
bool CDataBase::store( std::string uid, std::string s)
{
    streampos   spos;

    if ( find( uid, spos) )
    {
        return false;
    }
    else
    {
        fb.pubseekoff( 0, ios::end);
        ofile << s << endl;
        return true;
    }
}
bool CDataBase::retrieve( std::string uid, std::string &s)
{
    streampos   spos;

    if ( find( uid, spos) )
    {
        fb.pubseekoff( spos, ios::beg);
        getline( ifile, s);
        return true;
    }
    else
        return false;
}
bool CDataBase::remove( std::string uid)
{
    streampos   spos;

    if ( find( uid, spos) )
    {
        fb.pubseekoff( spos, ios::beg);
        ofile << "DELETED";
        return true;
    }
    else
        return false;
}