// -*- C++ -*-
#ifndef RIFEEDBACK_H
#define RIFEEDBACK_H
/* Copyright 1996 
 * Thu Jun  5 11:12:38 1997  Brian Smits  (bes@phoenix.cs.utah.edu)
 * 
 * RiFeedback.H
 * 
 *	
 * 
 * $Id: RiFeedback.H,v 1.3 1998/06/22 17:12:22 bes Exp $ 
 * 
 */
#ifndef RICOMMON_H
#include <RiCommon.H>
#endif


#include <iostream.h>  // needed for the template at the bottom.

/***************************************************************
CLASS
    RiFeedback
     Responsible for giving feedback to the user (Errors, Stats, Warnings, and Info)

DESCRIPTION
     This class functions much like an ostream.  The operator << is overloaded (as an
     inline) to work for RiFeedback classes and RiFeedback terminators.  The Terminators
     allow fatal errors to cause a clean crash.  Critical errors are those where there is
     a significant amount of data loss.  A crash might not be warrented.

****************************************************************/

class RiFeedback {
  public:
    enum Terminator {endl, fatal, critical};
    // GROUP: Constructors and assignment
    RiFeedback() {}
				//// Destructor
    virtual ~RiFeedback() {}
				// GROUP: Accessors
				//// Return the error feedback handler
    static RiFeedback &Error();
				//// Return the warning feedback handler
    static RiFeedback &Warning();
				//// Return the info feedback handler
    static RiFeedback &Info();
				//// Return the stats feedback handler
    static RiFeedback &Statistics();
				//// Set the error feedback handler
    static void SetError(RiFeedback *);
				//// Set the warning feedback handler
    static void SetWarning(RiFeedback *);
				//// Set the info feedback handler
    static void SetInfo(RiFeedback *);
				//// Set the stats feedback handler
    static void SetStatistics(RiFeedback *);
				//// return an ostream that will accept the data.
    virtual ostream &GetOStream()=0;
				// GROUP: Members
				//// Do any actions required at the end of a message
				// The default is to send an endl (endline) to GetOStream
    virtual void EndOfInput(Terminator);
				//// Abort the program (perhaps cleaning up and saving partial work)
    static void Abort();
  private:
    ////Copy Constructor
    RiFeedback(const RiFeedback &);
    //// Assignment
    RiFeedback &operator=(const RiFeedback &);

    static RiFeedback *warningHandler;
    static RiFeedback *errorHandler;
    static RiFeedback *infoHandler;
    static RiFeedback *statsHandler;
};


/***************************************************************
CLASS
    RiNullFeedback
     Toss all messages into the bit basket.

****************************************************************/

class RiNullFeedback : public RiFeedback {
  public:
    ostream &GetOStream();
  private:
};

/***************************************************************
CLASS
    RiStdoutFeedback
     send messages to stdout

****************************************************************/

class RiStdoutFeedback : public RiFeedback {
  public:
    ostream &GetOStream();
};

/***************************************************************
CLASS
    RiStderrFeedback
     Send messages to stderr

****************************************************************/

class RiStderrFeedback : public RiFeedback {
  public:
    ostream &GetOStream();
};


/***************************************************************
CLASS
    RiOStreamFeedback
     Send messages to a user-defined stream (such as an ofstream)

****************************************************************/

class RiOStreamFeedback : public RiFeedback {
  public:
    RiOStreamFeedback(ostream &out);
    ostream &GetOStream();
  private:
    ostream &out;
};



/**********************************************************
// Inlines (here to prevent too many functions getting generated by the templates)
// 
// ********************************************************/


inline RiFeedback  &operator<<(RiFeedback &out, RiFeedback::Terminator term)
{
    out.EndOfInput(term);
    if(term == RiFeedback::fatal)
      RiFeedback::Abort();
    return out;
}

template<class T> inline RiFeedback &operator<<(RiFeedback &out, T thing)
{
    out.GetOStream() << thing;
    return out;
}


#endif /* RIFEEDBACK_H */

