/** \file
 *
 *  Contains the LogEntry class definition.
 *
 *  Copyright (c) 2007,2008,2009 MBARI
 *  MBARI Proprietary Information.  All Rights Reserved
 *
 */

#ifndef LOGENTRY_H_
#define LOGENTRY_H_

#include "io/InStream.h"
#include "io/OutStream.h"
#include "logger/Logger.h"
#include "Service.h"
#include "utils/Str.h"
#include "utils/Timestamp.h"

class Logger;
class Unit;

/**
 *  One "entry" in a LogQueue.  Implementations of LogEntry are responsible
 *  for serializing and unserializing themselves to and from binary streams
 *  (via Read() and write() methods) and for serializing themselves to a
 *  text stream (via the toString() method).
 *
 *  Base class.  More specialized forms (DataEntry, EventEntry, SyslogEntry)
 *  derive from this class.
 *
 *  \ingroup logging
 */
class LogEntry
{
public:

    /// Defines an enum for "typing" the various LogEntries
    typedef enum
    {
        NOT_LOG_ENTRY =  -1,
        EVENT_LOG_ENTRY =  0,
        DIRECTORY_LOG_ENTRY =  1,
        DATA_LOG_ENTRY =   2,
        SYSLOG_LOG_ENTRY = 3,
    } Type;

    static const int TYPE_MASK = 0x0003;

    /// Destructor
    virtual ~LogEntry();

    /// Read in a new entry from a stream
    static LogEntry* Read( Timestamp& timeBase, Timespan& timeAdjust, InStream &inStream, Logger& logger, bool& error );

    /// Send payload to a stream
    virtual unsigned int write( Timestamp& timeBase, OutStream& logStream ) const = 0;

    /// Convert payload to Str
    virtual Str toString( const Unit* unit = NULL ) const = 0;

    /// Accessors
    const Timestamp& getTimestamp( void ) const
    {
        return timestamp_;
    };

    // Techically I shouldn't allow this but it is needed for the
    // log unserialization
    const Timestamp& setTimestamp( const Timestamp &newTime )
    {
        timestamp_ = newTime;
        return timestamp_;
    };
    const Timestamp& setTimestamp( const double newTime )
    {
        timestamp_ = newTime;
        return timestamp_;
    };

    Type getType( void ) const
    {
        return type_;
    };

    Service::ServiceType getServiceType( void ) const
    {
        return serviceType_;
    }

    /// Convert types to Strs
    static const char *TypeToString( Type theType );

protected:

    /// Constructor
    LogEntry( Type myType, const Timestamp& timestamp = Timestamp::NOT_SET_TIME, const Service::ServiceType serviceType = Service::SERVICE_UNSPECIFIED );

    static bool ReadTimestamp( Timestamp& timestamp, bool& changed, InStream& inStream, Logger& logger, Logger::TimePrecisionType timePrecision );

    unsigned int writeTimestamp( const Timestamp& timeBase, bool changed, OutStream & logStream, Logger::TimePrecisionType timePrecision ) const;


    /// Stores the type of a given LogEntry
    Type type_;

    Timestamp timestamp_;

    static const Str UNKNOWN;

    /// Used by LoggerRules::ServiceTypeRule
    Service::ServiceType serviceType_;

private:
    // Note that the copy constructor below is private and not given a body.
    // Any attempt to call it will return a compiler error.
    LogEntry( const LogEntry& old ); // disallow copy constructor


};

#endif /*LOGENTRY_H_*/
