/* ======================================================================== *\
!
! *
! * This file is part of MARS, the MAGIC Analysis and Reconstruction
! * Software. It is distributed to you in the hope that it can be a useful
! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
! * It is distributed WITHOUT ANY WARRANTY.
! *
! * Permission to use, copy, modify and distribute this software and its
! * documentation for any purpose is hereby granted without fee,
! * provided that the above copyright notice appear in all copies and
! * that both that copyright notice and this permission notice appear
! * in supporting documentation. It is provided "as is" without express
! * or implied warranty.
! *
!
!
!   Author(s): Thomas Bretz, 11/2003 <mailto:tbretz@astro.uni-wuerzburg.de>
!              Antonio Stamerra, 05/2004 <mailto:antonio.stamerra@pi.infn.it>
! 
!   Copyright: MAGIC Software Development, 2000-2003
!
!
\* ======================================================================== */

//////////////////////////////////////////////////////////////////////////////
//
//  MReportTrigger
//
// This is the class interpreting and storing the TRIGGER-REPORT information.
//  Updated to add IPR; data format follows TDAS 00-07
//
//////////////////////////////////////////////////////////////////////////////
#include "MReportTrigger.h"

#include "MParList.h"

#include "MLogManip.h"
#include "MTriggerIPR.h"
#include "MTriggerCell.h"
#include "MTriggerBit.h"
#include "MTriggerPrescFact.h"
#include "MTriggerLiveTime.h"

ClassImp(MReportTrigger);

using namespace std;

// --------------------------------------------------------------------------
//
// Default construtor. Initialize identifier to "TRIGGER-REPORT"
//
MReportTrigger::MReportTrigger() : MReport("TRIGGER-REPORT")
{
    fName  = "MReportTrigger";
    fTitle = "Class for TRIGGER-REPORT information";
}

// --------------------------------------------------------------------------
//
// FindCreate the following objects:
//  - MTriggerIPR
//  - MTriggerCell
//  - MTriggerBit
//  - MTriggerPrescFact
//
Bool_t MReportTrigger::SetupReading(MParList &plist)
{
  fPixel = (MTriggerIPR*)plist.FindCreateObj("MTriggerIPR");
  if (!fPixel)
    return kFALSE;

  fCell = (MTriggerCell*)plist.FindCreateObj("MTriggerCell");
  if (!fCell)
    return kFALSE;

  fBit = (MTriggerBit*)plist.FindCreateObj("MTriggerBit");
  if (!fBit)
    return kFALSE;

  fPrescFactor = (MTriggerPrescFact*)plist.FindCreateObj("MTriggerPrescFact");
  if (!fPrescFactor)
    return kFALSE;

  fLiveTime = (MTriggerLiveTime*)plist.FindCreateObj("MTriggerLiveTime");
  if (!fLiveTime)
    return kFALSE;
  
  return MReport::SetupReading(plist);
}

// --------------------------------------------------------------------------
//
// Interprete the Cell rates part of the report
//  Read 32 floats separated with a blank
//
Bool_t MReportTrigger::InterpreteCell(TString &str)
{
  Int_t len=0, n, i=0;
  Int_t gsNCells=32;

  for (i=0;i<gsNCells;i++)
    {
      n = sscanf(str.Data(), " %f %n", &fCell->fCellRate[i], &len);
      if (n!=1)
	{
	  *fLog << warn << "WARNING - Cell Scaler Value #" << i << " missing." << endl;
	  return kCONTINUE;
	}
      str.Remove(0, len); // Remove cell rates from report string
    }

  str=str.Strip(TString::kLeading);  

      *fLog << warn << "Cell ok!" <<endl;
  return kTRUE;
}

// --------------------------------------------------------------------------
//
// Interprete the Prescaling factors part of the report
//
Bool_t MReportTrigger::InterpretePrescFact(TString &str)
{
  Int_t len=0, n, i=0;
  Int_t gsNPrescFacts=8;
  
  str.Remove(0, 1);
  *fLog << warn << str<<endl;

  for (i=0;i<gsNPrescFacts;i++)
    {
    const Int_t ws = str.First(' ');
    if (ws<=0)
       {
	 *fLog << warn << "WARNING - Cannot determine Prescaling factor #" << i << " descriptor" << endl;
        return kCONTINUE;
       }
    TString descriptor = str(0, ws);
    *fLog  << descriptor <<endl;
    str.Remove(0, ws);
      
      n = sscanf(str.Data(), " %li %n", &fPrescFactor->fPrescFact[i], &len);
      if (n!=1)
	{
	  *fLog << warn << "WARNING - prescaler factor " << i << " missing." << endl;
	  return kCONTINUE;
	}
      str.Remove(0, len); // Remove Prescal. factors from report string
      *fLog << warn << fPrescFactor->fPrescFact[i]<<endl;
    }
  str=str.Strip(TString::kLeading);  
  
  return kTRUE;
}

// --------------------------------------------------------------------------
//
// Interprete the Scaler with Live-Deadtime part of the report
//  Read 4x5 integers separated with a blank
//
Bool_t MReportTrigger::InterpreteLiveTime(TString &str)
{
  Int_t len, n, i=0;
  Int_t gsNScalers=5;
  Int_t  dLSB, dMSB,lLSB, lMSB;

  for (i=0;i<gsNScalers;i++)
    {
      n = sscanf(str.Data(), " %d %d %d %d %n", &lLSB, &lMSB,&dLSB, &dMSB, &len);
      if (n!=4)
	{
	  *fLog << warn << "WARNING - Live-Deadtime Scaler Value #" << i << " missing." << endl;
	  return kCONTINUE;
	}

      str.Remove(0, len); // Remove Live-Deadtimes from string

      //convert to seconds and fill container
      // (FIXME! only the MSB (seconds is now considered)
      (fLiveTime->fLiveTime)[i] = lMSB;
      (fLiveTime->fDeadTime)[i] = dMSB;      
    }

  str=str.Strip(TString::kLeading);  

  return kTRUE;
}

// --------------------------------------------------------------------------
//
// Interprete the Bit rates part of the report
// 20 integers. First and last two are not used
//
Bool_t MReportTrigger::InterpreteBit(TString &str)
{
  Int_t len, n, i=0;
  Int_t gsNBits=20;
  
  for (i=0;i<gsNBits;i++)
    {
      n = sscanf(str.Data(), " %f %n", &fBit->fBit[i], &len);
      if (n!=1)
	{
	  *fLog << warn << "WARNING - Bit rate #" << i << " missing." << endl;
	  return kCONTINUE;
	}
      str.Remove(0, len); // Remove output bit rates from string
    }

  str=str.Strip(TString::kLeading);  

  return kTRUE;
}

// --------------------------------------------------------------------------
//
// Interprete the L1 and L2 table names
// 1String + 1Int +1 String
//
Bool_t MReportTrigger::InterpreteL1L2Table(TString &str)
{
    const Int_t wsL1 = str.First(' ');
 
    if (wsL1<=0)
       {
        *fLog << warn << "WARNING - Cannot determine name of L1 trigger table." << endl;
        return kCONTINUE;
       }
    
    TString L1tablename = str(0, wsL1);
    str.Remove(0, wsL1);

    // remove an integer between names
    Int_t len;
    Int_t mi;
    Int_t n=sscanf(str.Data(), "%d %n", &mi, &len);
    if (n!=1)
      {
        *fLog << warn << "WARNING - Not enough arguments." << endl;
        return kCONTINUE;
    }
    str.Remove(0, len);

    // L2 tablename
    const Int_t wsL2 = str.First(' ');
 
    if (wsL2<=0)
      {
        *fLog << warn << "WARNING - Cannot determine name of L2 trigger table." << endl;
        return kCONTINUE;
      }    
    TString L2tablename = str(0, wsL2);
    str.Remove(0,wsL2);
    str.Strip(TString::kBoth);
    
    return kTRUE;
}

// --------------------------------------------------------------------------
//
// Interprete a part of the report without meaning by this time
// 18 integers
//
Bool_t MReportTrigger::InterpreteDummy(TString &str)
{
  Int_t len, n, i=0;
  Int_t gsNDummies=18;
  Int_t dummy;  

  for (i=0;i<gsNDummies;i++)
    {
      n = sscanf(str.Data(), " %d %n", &dummy, &len);
      if (n!=1)
	{
	  *fLog << warn << "WARNING - Dummy #" << i << " missing." << endl;
	  return kCONTINUE;
	}
      str.Remove(0, len); // Remove dummies from report string
    }

  str=str.Strip(TString::kLeading);  

  return kTRUE;
}

// --------------------------------------------------------------------------
//
// Interprete the IPR part of the report
//
Bool_t MReportTrigger::InterpreteIPR(TString &str)
{


  *fLog << warn << "IPR ok!" <<endl;
  return kTRUE;
}


// --------------------------------------------------------------------------
//
// Interprete the body of the TRIGGER-REPORT string
//  Read comments for details
//
Int_t MReportTrigger::InterpreteBody(TString &str)
{
    str = str.Strip(TString::kLeading);
 
    // Extract trigger table name
    const Int_t ws = str.First(' ');
 
   if (ws<=0)
    {
        *fLog << warn << "WARNING - Cannot determine name of trigger table." << endl;
        return kCONTINUE;
    }

    TString tablename = str(0, ws);
    str.Remove(0, ws);

    // Read the cell rates (32 fields)
    if (!InterpreteCell(str))
      return kCONTINUE;

    // Read L1 and L2 table name (2 fields)
    if (!InterpreteL1L2Table(str))
      return kCONTINUE;    

    // Read prescaling factors  (2x8 fields)
    if (!InterpretePrescFact(str))
      return kCONTINUE;
    
    // Read livetime and deadtime (5x4 fields)
    if (!InterpreteLiveTime(str))
      return kCONTINUE;

    // Read L2 outout bit rates
    if (!InterpreteBit(str))
      return kCONTINUE;

    // Read global rates (before and after prescaling)
    Int_t len, n;
    n = sscanf(str.Data(), " %f %f %n", &fL2BeforePrescaler, &fL2AfterPrescaler, &len);
    if (n!=2)
    {
         *fLog << warn << "WARNING - Couldn't read Trigger rates." << endl;
        return kFALSE;
    }
    str.Remove(0,len);
    str.Strip(TString::kBoth);

    // Read 18 dummy fields
    if (!InterpreteDummy(str))
      return kCONTINUE;

    // Read IPR
    if (!InterpreteIPR(str))
      return kCONTINUE;

    /*

    // Read Individual pixel rates
    pos = str.Data();
     end = str.Data() + 344;
 
    Int_t i=0;
    while (pos < end)
    {
        const Char_t hex[4] = { pos[0], pos[1], pos[2], 0 };
        n = sscanf(hex, "%hx", &fRates->fRates[i++]);
	pos++;
        if (n!=1)
        {
            *fLog << warn << "WARNING - Rate #" << i << " missing." << endl;
            return kFALSE;
        }
    }

    */

    str.Remove(0,len);
    str.Strip(TString::kBoth);

    return str==(TString)"OVER" ? kTRUE : kCONTINUE;
}
