/**
 * Class ITieredTextBuffer: Ojbects of this class act like C++ ostream objects
 *
 * They support operator<< for all built-in types.  ITieredTextBuffer also supports
 * the retrieval of textual information for later analysis.  Information is marked
 * with a level of importance to permit the adjustment of detail when the text is
 * printed.
 *
 * @package Test Framework
 * @category Testing
 *
 * @author Alan Liu
 * @task Initial Test Framework
 * @author Esther Tong
 * @task TestFrameworkLite
 * @author David McCusker, Christoper Miller, Carol Widra, and Kwansook Nam
 * @task Many of the other Contributors to TestFramework
 *
 * @copyright
 *      IBM Open Class Library
 *      (C) Copyright International Business Machines Corporation 1997
 *      Licensed Material - Program-Property of IBM - All Rights Reserved.
 *
 */
// Revision: 22  1.13.1.4  source/core/testfw/ittxtbuf.hpp, testfw, ioc.v400, 980918  


#ifndef _ITTXTBUF_
#define _ITTXTBUF_

#if __IBMCPP__ >= 400
#pragma namemangling(compat)
#endif

class ITieredText;
class ITieredTextBuffer;

#include "iprimtyp.hpp"

#include <istring.hpp>
#include <stdio.h>

#ifndef _ITFWPL_
#include <itfwpl.hpp>      // pragma library definitions
#endif

#pragma enum(4)
#pragma pack(push,4)

//-----------------------------------------------------------------------------
/**
 * ITieredTextBuffer Class
 *
 * Clients use ITieredTextBuffer as if it were a C++ ostream object. It has operator<<
 * methods for all built-in types.
 *
 * To write out diagonostic text from a test, use the member function outputTextStream,
 * which recognizes the standard C++ << operator for all built-in types.  Text output
 * produced with outputTextStream displays to the console and is also saved in a
 * ITieredTextBuffer within the test.  You can the log the test, including the text
 * buffer.  If a test fails, you can retieve the associated diagnostic text to determine
 * the cause of the failure.
 *
 * outputTestStream returns a pointer to a ITieredTextBuffer object that contains the
 * text.  Objects of the class ITieredTextBuffer act like C++ ostream objects.  They
 * support << operators for all built-in types.
 *
 * ITieredTextBuffer has some additional functionality beyond that of ostream to support
 * retrieving textual information for later analysis.  Information is marked with a
 * level of importance.  This permits showing a little or a lot of detail when the
 * text is printed.
 *
 * Most text occupies the tier kNormal.  Important information that should not be missed
 * occupies tier kGeneral or kHeadline.  Detailed information that can usually be
 * ignored occupies tier kDetail or kDebug.
 *
 * This is a list of available tiers in order of least detailed to most detailed:
 *
 *<PRE>
 *     kTop:       Most general information
 *     kHeadline:  One-line information
 *     kGeneral:   General interest
 *     kNormal:    Default
 *     kDetail:    Detail not usually needed
 *     kDebug:     Only needed during debugging
 *     kBottom:    Lowest tier, most detailed
 *</PRE>
 *
 */
class ITieredTextBuffer {
public:
//-------------------------------------------------------------------------
// Canonical methods

/** @group Construction, Destruction, and Assignment */

/**
 * Default Constructor
 */
ITieredTextBuffer();


/**
 * Constructor
 *
 * @param ITieredTextBuffer
 *
 */
ITieredTextBuffer(const ITieredTextBuffer&);


/**
 * Standard Assignment Operator
 */
ITieredTextBuffer& operator=(const ITieredTextBuffer&);


/**
 * Destructor
 */
virtual ~ITieredTextBuffer();


//-------------------------------------------------------------------------
// Tier definitions
//-------------------------------------------------------------------------

enum ETier {
        kTop = 0,                   // Top tier, most general information
        kHeadline = 0x10,       // One-liner information
        kGeneral = 0x20,        // Information of general interest
        kEphemeral = 0x2F,      // ' Only shows on screen; not saved '
        kNormal = 0x30,         // Default tier
        kDetail = 0x40,         // Detailed information not usually needed
        kDebug = 0x50,          // Information only needed during debugging
        kBottom = 0x5F          // Lowest tier, most detailed information
};

//-------------------------------------------------------------------------
// C++ ostream-style output
//-------------------------------------------------------------------------
/**
 * C++ ostream-style output operator for long double.
 */
virtual ITieredTextBuffer& operator<<(const long double);   // numeric

/**
 * C++ ostream-style output operator for double.
 */
virtual ITieredTextBuffer& operator<<(const double);        // numeric

/**
 * C++ ostream-style output operator for float.
 */
virtual ITieredTextBuffer& operator<<(const float);         // numeric

/**
 * C++ ostream-style output operator for long.
 */
virtual ITieredTextBuffer& operator<<(const long);          // numeric

/**
 * C++ ostream-style output operator for int.
 */
virtual ITieredTextBuffer& operator<<(const int);           // numeric

/**
 * C++ ostream-style output operator for short.
 */
virtual ITieredTextBuffer& operator<<(const short);         // numeric

/**
 * C++ ostream-style output operator for signed char.
 */
virtual ITieredTextBuffer& operator<<(const signed char);   // numeric

/**
 * C++ ostream-style output operator for unsigned long.
 */
virtual ITieredTextBuffer& operator<<(const unsigned long); // numeric

/**
 * C++ ostream-style output operator for unsigned short.
 */
virtual ITieredTextBuffer& operator<<(const unsigned short);// numeric

/**
 * C++ ostream-style output operator for unsigned int.
 */
virtual ITieredTextBuffer& operator<<(const unsigned int);  // numeric

/**
 * C++ ostream-style output operator for unsigned char.
 */
virtual ITieredTextBuffer& operator<<(const unsigned char); // numeric

/**
 * C++ ostream-style output operator for char.
 */
virtual ITieredTextBuffer& operator<<(const char);          // text

/**
 * C++ ostream-style output operator for char*.
 */
virtual ITieredTextBuffer& operator<<(const char*);         // text

/**
 * C++ ostream-style output operator for IString.
 */
//virtual ITieredTextBuffer& operator<<(const IString&);    // text


/**
 *This allows users to call "endl" with ITieredTextBuffer.
 */
typedef ITieredTextBuffer& (*endlfn)(ITieredTextBuffer&);
virtual ITieredTextBuffer& operator<<(endlfn);

// virtual ITieredTextBuffer& operator<<(const void*);

/**
 * Sets the indent level for subsequent output via the operator<< methods.
 *
 * If new indent is zero, text will be flushed left.  Indentation only affects
 * text that is added to this object via one of the <<operators.
 *
 * @param short    Level of indentation
 *
 * @see indent
 *
 */
unsigned short setIndent(unsigned short); // Set the indentation for incoming text


/**
 * Sets the indent level for subsequent output relative to the current indent level.
 *
 * @param short Level of indentation
 *
 * @see indent
 *
 */
unsigned short setRelativeIndent(short);  // set the indentation relatively


/**
 * Returns the current indentation level setting.
 *
 * @return indent level for output
 *
 * @see setIndent
 * @see setRelativeIndent
 *
 */
unsigned short indent() const;


/**
 * Changes the tier of all subsequently streamed text to newTier.
 *
 * It only affects future calls to operator<<.  setTier pins newTier
 * to the range kTop...kBottom.
 *
 * @param newTier  Tier object to use
 *
 * @see tier
 *
 */
ETier setTier(ITieredTextBuffer::ETier newTier); // Set the tier for incoming text


/**
 * Returns the current tier object.
 *
 * @return current tier object
 *
 * @see setTier
 *
 */
ETier tier() const;


/**
 * Change tier to new setting and save old value.
 *
 * Pushes newTier onto an internal stack of ETiers and makes it the new tier
 * by calling setTier.  A subsequent call to popTier will restore the previous
 * tier.  If the internal stack is full, the stack is unchanged and newTier
 * does not get pushed.
 *
 * @param newTier     Tier object to use
 *
 * @see popTier
 *
 */
void pushTier(ETier newTier); // Change tier and save old value


/**
 * Restore tier to value before last pushTier.
 *
 * Pops the tier at the top of the stack, as previously pushed on by pushTier,
 * and returns it.  The tier is set to the value it had before that last call
 * to pushTier.
 *
 * @return a Tier object
 *
 * @see pushTier
 *
 */
ETier popTier();              // Restore tier to value before last pushTier


//-------------------------------------------------------------------------
/** @group Echo and Output Configuration */


/**
 * Set the tier above which text is echoed to console.
 *
 * This method sets the tier level at which echoing occurs.  ITieredTextBuffer
 * objects echo all output sent to them (via the operator<< method) to
 * standard output.  Echoing only happens for text above a certain tier, which
 * is set by these methods.  Subclasses may override setEchoTier if they want
 * notification when the echo tier changes.
 *
 * @param ETier  Tier level to set
 *
 * @see echoTier
 *
 */
void setEchoTier(ETier); // Set the tier above which text is echoed to console


/**
 * Returns the ETier level at which echo is set.
 *
 * @return ETier level
 *
 * @see setEchoTier
 *
 */
ETier echoTier() const;


/**
 * Attempts to open the specified log file.
 *
 * Causes output to be displayed to standard output as well as to the log file.
 *
 * @param logFileName  String value of the log file to open
 *
 */
void openLog(const char* logFileName);


//_____________________________________________________________________________
private:
void indentAndPrintText(const IString&);
virtual void printText(const ITieredText&);

//-------------------------------------------------------------------------
// Data members for tiers and indentation
//-------------------------------------------------------------------------
enum { kTierStackDepth = 16 }; // Tier for next ostream output
ETier fTierStack[kTierStackDepth];
unsigned short fTierStackTop;

enum { kMaxIndent = 25 };      // Maximum indentation level allowed
ETier fIndentTier[kMaxIndent];
unsigned short fIndentLevel;   // Current indent level, 0 = none
bool fIndentPending;           // Indent before next text
FILE* flogFile;
bool  fdoLogging;
//-------------------------------------------------------------------------
// Data members for text collection, echoing, and output streams
//--------------------------------------------------------------------------
ETier fEchoTier;              // Tier threshold for echoing

friend ITieredTextBuffer& endl(ITieredTextBuffer&); // Overriding "ostream& endl(ostream&)"
};

#pragma pack(pop)
#pragma enum(pop)

#if __IBMCPP__ >= 400
#pragma namemangling()
#endif

#endif // _ITTXTBUF_
