////////////////////////////////////////////////////////////////////////////////
// 
// ScreenReport.cc
//
//    produced: 2024-04-15 jr
// 
////////////////////////////////////////////////////////////////////////////////

#include "ScreenReport.hh"

namespace topcom {

  const char* ScreenReport::field_separator = " | ";

  // report only according to frequency settings:
  bool ScreenReport::decide_report(const size_type count) {
    MessageStreams::debug() << message::lock;
    MessageStreams::debug() << "deciding about screen report ..." << std::endl;
    MessageStreams::debug() << "... countdown before call: " << _countdown << " ..." << std::endl;
    _countdown -= (count - _old_count);
    _old_count = count;
    MessageStreams::debug() << "... countdown after call: " << _countdown << " ..." << std::endl;
    if (_countdown <= 0) {
      MessageStreams::debug() << "... yes: reporting ..." << std::endl;
      _countdown = CommandlineOptions::report_frequency();
      MessageStreams::debug() << "... done" << std::endl;
      MessageStreams::debug() << message::unlock;
      return true;
    }
    else {
      MessageStreams::debug() << "no: skipping report this time" << std::endl;
      MessageStreams::debug() << message::unlock;
      return false;
    }
  }

  Message& ScreenReport::execute_ext_worker_report(Message&                    msg,
						   const int                   workerID,
						   const size_type             nodecount,
						   const size_type             symcount,
						   const size_type             totalcount,
						   const size_type             deadendcount,
						   const size_type             earlydeadendcount,
						   const progress_vector_type& progressvector) const {
    if (!msg.is_active()) {
      return msg;
    }
    msg << message::lock;
    report_workerID(msg, workerID);
    msg << field_separator;
    report_nodecount(msg, nodecount);
    msg << field_separator;
    report_symcount(msg, symcount);
    msg << field_separator;
    if (!CommandlineOptions::skip_orbitcount()) {
      report_totalcount(msg, totalcount);
      msg << field_separator;
    }
    report_deadendcount(msg, deadendcount);
    msg << field_separator;
    report_earlydeadendcount(msg, earlydeadendcount);
    msg << field_separator;
    report_progressvector(msg, progressvector);
    msg << std::endl;
    msg << message::unlock;
    return msg;
  }
  
  Message& ScreenReport::execute_ext_master_report(Message&        msg,
						   const int       idlethreads,
						   const size_type nodecount,
						   const size_type symcount,
						   const size_type totalcount,
						   const size_type deadendcount,
						   const size_type earlydeadendcount,
						   const size_type workbuffersize,
						   const size_type minworkbuffersize,
						   const size_type nodebudget) const {
    if (!msg.is_active()) {
      return msg;
    }
    msg << message::lock;
    report_master(msg);
    msg << field_separator;
    report_nodecount(msg, nodecount);
    msg << field_separator;
    report_symcount(msg, symcount);
    msg << field_separator;
    if (!CommandlineOptions::skip_orbitcount()) {
      report_totalcount(msg, totalcount);
      msg << field_separator;
    }
    report_deadendcount(msg, deadendcount);
    msg << field_separator;
    report_earlydeadendcount(msg, earlydeadendcount);
    msg << field_separator;
    if (CommandlineOptions::parallel_enumeration()) {
      report_workbuffersize(msg, workbuffersize);
      msg << field_separator;
      if (CommandlineOptions::workbuffercontrol()) {
	report_minworkbuffersize(msg, minworkbuffersize);
	msg << field_separator;
      }
      else {
	report_nodebudget(msg, nodebudget);
	msg << field_separator;
      }
      report_idlethreads(msg, idlethreads);
    }
    msg << std::endl;
    msg << message::unlock;
    return msg;
  }
    
  Message& ScreenReport::execute_flip_distclass_report(Message&                    msg,
						       const int                   workerID,
						       const size_type             nodecount,
						       const size_type             symcount,
						       const size_type             totalcount,
						       const size_type             storedcount,
						       const size_type             flipcount,
						       const size_type             flipdist) const {
    if (!msg.is_active()) {
      return msg;
    }
    msg << message::lock;
    report_nextdistclass(msg);
    msg << field_separator;
    report_workerID(msg, workerID);
    msg << field_separator;
    report_nodecount(msg, nodecount);
    msg << field_separator;
    report_symcount(msg, symcount);
    msg << field_separator;
    if (!CommandlineOptions::skip_orbitcount()) {
      report_totalcount(msg, totalcount);
      msg << field_separator;
    }
    report_storedcount(msg, storedcount);
    msg << field_separator;
    report_flipcount(msg, flipcount);
    msg << field_separator;
    report_flipdist(msg, flipdist);
    msg << std::endl;
    msg << message::unlock;
    return msg;
  }

  Message& ScreenReport::execute_flip_node_report(Message&                    msg,
						  const int                   workerID,
						  const size_type             nodecount,
						  const size_type             symcount,
						  const size_type             totalcount,
						  const size_type             storedcount,
						  const size_type             flipcount,
						  const size_type             flipdist) const {
    if (!msg.is_active()) {
      return msg;
    }
    msg << message::lock;
    report_indistclass(msg);
    msg << field_separator;
    report_workerID(msg, workerID);
    msg << field_separator;
    report_nodecount(msg, nodecount);
    msg << field_separator;
    report_symcount(msg, symcount);
    msg << field_separator;
    if (!CommandlineOptions::skip_orbitcount()) {
      report_totalcount(msg, totalcount);
      msg << field_separator;
    }
    report_storedcount(msg, storedcount);
    msg << field_separator;
    report_flipcount(msg, flipcount);
    msg << field_separator;
    report_flipdist(msg, flipdist);
    msg << std::endl;
    msg << message::unlock;
    return msg;
  }
  
  Message& ScreenReport::report_master(Message& msg) const {
    return msg << "*** master ***";
  }

  Message& ScreenReport::report_workerID(Message& msg,
					 const int workerID) const {
    return msg << "+ worker "<< std::setw(5) << workerID;
  }

  Message& ScreenReport::report_nextdistclass(Message& msg) const {
    return msg << "*** next distclass ***";
  }

  Message& ScreenReport::report_indistclass(Message& msg) const {
    return msg << "+ distclass continued ";
  }

  Message& ScreenReport::report_nodecount(Message& msg,
					  const size_type nodecount) const {
    return msg << "n: " << std::setw(15) << nodecount;
  }
  
  Message& ScreenReport::report_symcount(Message& msg,
					 const size_type symcount) const {
    return msg << "sym: " << std::setw(15) << symcount;
  }
  
  Message& ScreenReport::report_totalcount(Message& msg,
					   const size_type totalcount) const {
    return msg << "tot: " << std::setw(15) << totalcount;
  }
  
  Message& ScreenReport::report_deadendcount(Message& msg,
					     const size_type deadendcount) const {
    return msg << "ldead: " << std::setw(12) << deadendcount;
  }
  
  Message& ScreenReport::report_earlydeadendcount(Message& msg,
						  const size_type earlydeadendcount) const {
    return msg << "edead: " << std::setw(15) << earlydeadendcount;
  }

  Message& ScreenReport::report_storedcount(Message& msg,
					    const size_type storedcount) const {
    return msg << "stored: " << std::setw(9) << storedcount;
  }

  Message& ScreenReport::report_flipcount(Message& msg,
					  const size_type flipcount) const {
    return msg << "flips: " << std::setw(12) << flipcount;
  }

  Message& ScreenReport::report_flipdist(Message& msg,
					  const size_type flipdist) const {
    return msg << "flip dist: " << std::setw(4) << flipdist;
  }
  
  Message& ScreenReport::report_workbuffersize(Message& msg,
					       const size_type workbuffersize) const {
    return msg << "n open: " << std::setw(6) << workbuffersize;
  }
  
  Message& ScreenReport::report_minworkbuffersize(Message& msg,
						  const size_type minworkbuffersize) const {
    return msg << "n open min: " << std::setw(6) << minworkbuffersize;
  }
  
  Message& ScreenReport::report_nodebudget(Message& msg,
					   const size_type nodebudget) const {
    return msg << "n budget: " << std::setw(9) << nodebudget;
  }
  
  Message& ScreenReport::report_idlethreads(Message& msg,
					    const int idlethreads) const {
    return msg << "t idle: " << std::setw(4) << idlethreads;
  }
  
  Message& ScreenReport::report_progressvector(Message& msg,
					       const progress_vector_type& progressvector) const {
    return msg << "progress [%]: " << progressvector;
  }

}; // namespace topcom
  
// eof ScreenReport.cc
