//Editor-Info: -*- C++ -*-
//
//Subject: TOVE project / pf
//
//File: debug.h
//
//Version: $Revision: 1.17 $
//
//State: $State: Exp $
//
//Date: $Date: 1998/10/05 14:08:26 $
//
//Organisation:
//      Helsinki University of Technology
//      Laboratory of Telecommunications Software and Multimedia
//
//Author:
//      Timo Kokkonen
//
//Description:
//      
//
//Copyright:
//      Copyright 1999 Helsinki University of Technology
//      ALL RIGHTS RESERVED BETWEEN JANUARY 1996 AND JUNE 1999.
//
//Licence:
//
//
//History:
//

#ifndef __PF_DEBUG_H__
#define __PF_DEBUG_H__

#include <typeinfo>
#include <string>

#include "state.h"
#include "protocol.h"
#include "frame.h"
#include "types.h"

#ifndef NO_EVENT
// For corba event.
#include "sf/orbscheduler.h"
#include "testing/event/pushsupplier_impl.h"
#endif

#define __DEBUG_PFDEBUG__
#define __DEBUG_USER__

#ifndef __DEBUG_PFDEBUG__
#define debugCreate(a) (void)a
#define debugDelete(a) (void)a
#define debugState(a, b) (void)a; (void)b
#define debugReceive(a, b) (void)a; (void)b
#define debugSendToA(a) (void)a
#define debugSendToB(a) (void)a
#define debugStartRun(a, b) (void)a; (void)b
#define debugEndRun()
#define debugExceptionThrown(a, b, c) (void)a; (void)b; (void)c
#define debugExceptionCatched(a) (void)a
#else
#define debugCreate(a) pfDebug::instance()->protocolCreated(a)
#define debugDelete(a) pfDebug::instance()->protocolDeleted(a)
#define debugState(a, b) pfDebug::instance()->changingState(a, b)
#define debugReceive(a, b) pfDebug::instance()->receiving(a, b)
#define debugSendToA(a) pfDebug::instance()->sendingToA(a)
#define debugSendToB(a) pfDebug::instance()->sendingToB(a)
#define debugStartRun(a, b) pfDebug::instance()->startRunning(a, b)
#define debugEndRun() pfDebug::instance()->endRunning()
#define debugExceptionThrown(a, b, c) pfDebug::instance()->exceptionThrown(a, b, c)
#define debugExceptionCatched(a) pfDebug::instance()->exceptionCatched(a)
#endif

// For user
#ifndef __DEBUG_USER__
#define debugUser(a) (void)a
#define debugPfUlong(a, b) (void)a; (void)b
#define debugString(a, b) (void)a; (void)b
#define debugFrame(a, b) (void)a; (void)b
#define debugTime()
#else
#define debugUser(a) pfDebug::instance()->traceUserProvided(a, __FILE__, __LINE__)
#define debugPfUlong(a, b) pfDebug::instance()->tracePfUlong(a, b, __FILE__, __LINE__)
#define debugString(a, b) pfDebug::instance()->traceString(a, b, __FILE__, __LINE__)
#define debugFrame(a, b) pfDebug::instance()->tracePfFrame(a, b, __FILE__, __LINE__)
#define debugTime() pfDebug::instance()->traceTimeStamp(__FILE__, __LINE__)
#endif

// For output control
#define debugOutputNull() pfDebug::instance()->setOutputToNull()
#define debugOutputCout() pfDebug::instance()->setOutputToCout()
#define debugOutputFile() pfDebug::instance()->setOutputToFile()
#define debugOutputCorba() pfDebug::instance()->setOutputToCorba()

// defines for output control
#define _OUTPUT_NULL_ 0
#define _OUTPUT_COUT_ 1
#define _OUTPUT_FILE_ 2
#define _OUTPUT_CORBA_ 3

class pfDebug
{
    public:
        static pfDebug *instance(void);
        virtual ~pfDebug(void);

        void protocolCreated(const pfProtocol *protocol_);
        void protocolDeleted(const pfProtocol *protocol_);
        void changingState(const pfState *oldState_, const pfState *newState_);
        void receiving(const pfProtocol *protocol_,
                       const pfTransporter *transporter_);
        void sendingToA(const pfTransporter *transporter_);
        void sendingToB(const pfTransporter *transporter_);
        void startRunning(const pfProtocol *protocol_,
                          const pfTransporter *transporter_);
        void endRunning(void);
        void exceptionThrown(pfUlong exception_,
                             const string &file_,
                             pfUlong line_);
        void exceptionCatched(pfUlong exception);

        void traceUserProvided(const string &output_,
                               const string &file_,
                               pfUlong line_);
        void tracePfUlong(const string &output_,
                          pfUlong value_,
                          const string &file_,
                          pfUlong line_);
        void traceString(const string &output_,
                         const string &value_,
                         const string &file_,
                         pfUlong line_);
        void tracePfFrame(const string &output_,
                          const pfFrame &frame_,
                          const string &file_,
                          pfUlong line_);

        void traceTimeStamp(const string &file_,
                            pfUlong line_);

        static string getStateName(const pfState *state_);
        static string getProtocolName(const pfProtocol *protocol_);
        static void eraseNamesHead(string &name_);
        static string serialnumberToString(pfMessenger::SerialNumber serialNumber_);

        string parseFileAndLine(const string &file_, const pfUlong line_);
        void printFrame(const pfFrame &frame_);
        string pfUlongToHexStr(pfUlong value_);

        void output(const string &debugInfo_) const;

        void setOutputToNull(void);
        void setOutputToCout(void);
        void setOutputToFile(void);
        void setOutputToCorba(void);

    protected:
        pfDebug(void);

    private:
        void initCorbaEvent(void);
	pfDebug(const pfDebug &other_);
	pfDebug &operator=(const pfDebug other_);

        static pfDebug *_only;

        pfUlong _output;
        const char *_logFile;
        
#ifndef NO_EVENT
        PushSupplier_impl *_supplier;
        string _eventServiceStr;
#endif
        const string _protocolCreated;
        const string _protocolDeleted;
        const string _debug;
        const string _change;
        const string _ptr_r;
        const string _receiv;
        const string _recvs;
        const string _sendToA;
        const string _sendToB;
        const string _startRun;
        const string _endRun;
        const string _runs;
        const string _error;
        const string _excepThrown;
        const string _excepCatched;
        const string _trace;
        const string _pfUlong;
        const string _string;
        const string _pfFrame;
        const string _eoFrame;
        const string _timeStamp;
};

#endif //__PF_DEBUG_H__


