#include <string>
#include <map>
#include "trigger.h"
#include "proc_stat.h"
#include "proc_cmd.h"
#include "msg.h"
#include "opus_exceptions.h"

//////////////////////////////////////////////////////////////////////////
//
// Method: Opus_env::define_pstat_trig
//
// Purpose:
//
//    Function template for creating PSTAT blackboard triggers.
//
// Description:
//
//    This method creates the PSTAT-related triggers for the HALT, RESU, 
//    SUSP, and REINIT commands, and the suspended trigger for processes
//    that already are suspended.
//    
// Returns:
//
//    none
//
// Exceptions thrown:
//
//    Severe<void*>  - if trigger construction fails;
//                     Severe.arg contains 0
//
// Example:
//
//    none
//
// Modification History:
//
// Date      OPR      Who         Reason
// --------- -------- ----------- ----------------------------------------
// 05/27/98  37796    WMiller     Initial code
// 03/15/00  40934    WMiller     Triggers associated with new blackboard
// 04/25/06  55700    Sontag      Can not use endl here without namespace
//////////////////////////////////////////////////////////////////////////

template<class T, class R>
void Opus_env::define_pstat_trig(
                                 const T*,           // I - dummy arg.
                                 const R*,           // I - dummy arg.
                                 const Pstat* pstat, // I - search template
                                 const double& rank, // I - trigger rank
                                 const std::string& mesg) // I - trigger name
{
   Trigger*   pstat_trig = 0;
   Pstat*     cond = 0;
   R*         pcmd = 0;
   Proc_cmd*  pcclr = 0;
   pair<map<double, Trigger*>::iterator, bool> ires;
       
   T* evt = 0;
   try {
      T::add_callback(0);
      evt = new T(pbb);
      cond = dynamic_cast<Pstat*>(pstat->clone());
      cond->search_mask();
      pcmd = new R(mesg);
      cond->set_field(pcmd);
      pcclr = new Proc_cmd();
      pcclr->fill(Field::FORCEPAD);
      pstat_trig = new Trigger(pebb, cond, mesg, pcclr, evt);
      ires = trigs.insert(make_pair(rank, pstat_trig));
      if (!ires.second) {
         Msg m;
         m << sev(Msg::E) << type(Msg::SEVERE) << "Opus_env::pstat_trigs - "
           << mesg << " Trigger insertion failed." << endm;
         delete pstat_trig;
         throw Severe<void*>(0);
      }
      delete cond;
      delete pcmd;
      delete pcclr;
      delete evt;
   }
   catch(Opus_exceptions& oe) {
      Msg m;
      m << sev(Msg::E) << type(Msg::SEVERE) << "Opus_env::pstat_trigs - "
        "Construction of the " << mesg << " Trigger did not complete normally."
        << oe.full() << endm;
      delete cond;
      delete pcmd;
      delete pcclr;
      delete evt;
      throw Severe<void*>(0);
   }
   catch(...) {
      Msg m;
      m << sev(Msg::E) << type(Msg::SEVERE) << "Opus_env::pstat_trigs - "
        "Construction of the " << mesg << " Trigger did not complete normally."
        << endm;
      delete cond;
      delete pcmd;
      delete pcclr;
      delete evt;
      throw Severe<void*>(0);
   }
}
