// =====================================================================
//  $Id: TExtractor.cc,v 1.4 2004/03/07 10:30:27 goiwai Exp $
//  $Name: CLDAQ-1-14-03 $
//  $Log: TExtractor.cc,v $
//  Revision 1.4  2004/03/07 10:30:27  goiwai
//  ROOTに組みこむためのおまじないマクロを埋めこみました。
//  全てにおいて完全に動作するわけではありません。
//
//  Revision 1.3  2003/10/06 17:02:36  goiwai
//  *** empty log message ***
//
//  Revision 1.2  2003/07/30 16:17:10  goiwai
//  ファイルにコミットログをつけることにしました.
//
// =====================================================================
#include "TExtractor.hh"
#include "TDataRecord.hh"
#include "TDataSection.hh"
#include "TDataSegment.hh"
#include "TDataElement.hh"

TExtractor::TExtractor( const Tstring& id, Tobject_t objecttype, Tint nevents, Tint usec )
  : theExtractorID( id ), theMatrixElement(), theSamplingRate( usec ),
    theDataFoundStatus( Tfalse ), theFillMatrixStatus( Tfalse )
{
  Tint ntuple;
  switch ( objecttype ) {
    case tObject1DHistogram:
      ntuple = 1;
      break;
    case tObject2DHistogram:
      ntuple = 2;
      break;
    case tObjectSubstituteGraph:
    case tObjectAppendGraph:
      ntuple = 2;
      break;
    case tObjectNtuple:
    default:
      ntuple = 0;
  }
  theMatrixElement = TMatrixElement( theExtractorID, objecttype, nevents, ntuple );
}

TExtractor::~TExtractor()
{;}

TDataSection TExtractor::FindDataSection( const TDataRecord& record, const Tstring& sectionid )
{
  theDataFoundStatus = Tfalse;
  TDataSection section;
  for ( Tint i = 0; i < (Tint)record.size(); i ++ ) {
    if ( record[ i ].GetID() == sectionid &&
	 record[ i ].GetObjectType() == tObjectDataSection &&
	 record[ i ].size() != 0 ) {
    //if ( record[ i ].GetID() == sectionid && record[ i ].size() != 0 ) {
      section = record[ i ];
      theDataFoundStatus = Ttrue;
      break;
    }
  }
  return section;
}

TDataSegment TExtractor::FindDataSegment( const TDataSection& section, const Tstring& segmentid )
{
  theDataFoundStatus = Tfalse;
  TDataSegment segment;
  for ( Tint i = 0; i < (Tint)section.size(); i ++ ) {
    if ( section[ i ].GetID() == segmentid &&
	 section[ i ].GetObjectType() == tObjectDataSegment &&
	 section[ i ].size() != 0 ) {
      //if ( section[ i ].GetID() == segmentid && section[ i ].size() != 0 ) {
      segment = section[ i ];
      theDataFoundStatus = Ttrue;
      break;
    }
  }
  return segment;
}

TDataElement TExtractor::FindDataElement( const TDataSegment& segment, const Tstring& elementid )
{
  theDataFoundStatus = Tfalse;
  TDataElement element;
  for ( Tint i = 0; i < (Tint)segment.size(); i ++ ) {
    if ( segment[ i ].GetID() == elementid &&
	 segment[ i ].GetElementType() != tTypeUnknown &&
	 segment[ i ].GetNumberOfPrimitives() != 0 &&
	 segment[ i ].GetObjectType() == tObjectDataElement ) {
      element = segment[ i ];
      theDataFoundStatus = Ttrue;
      break;
    }
  }
  return element;
}

TDataSegment TExtractor::FindDataSegment( const TDataRecord& record, const Tstring& sectionid, const Tstring& segmentid )
{
  return FindDataSegment( FindDataSection( record, sectionid ), segmentid );
}

TDataSegment TExtractor::FindDataSegment( const TDataRecord& record, Tstring id[ 2 ] )
{
  return FindDataSegment( FindDataSection( record, id[ 0 ] ), id[ 1 ] );
}

TDataElement TExtractor::FindDataElement( const TDataRecord& record, const Tstring& sectionid, const Tstring& segmentid, const Tstring& elementid )
{
  // DoesDataFound() がうまくいかない
  return FindDataElement( FindDataSegment( FindDataSection( record, sectionid ), segmentid ), elementid );
}

TDataElement TExtractor::FindDataElement( const TDataRecord& record, Tstring id[ 3 ] )
{
  return FindDataElement( FindDataSegment( FindDataSection( record, id[ 0 ] ), id[ 1 ] ), id[ 2 ] );
}

TDataElement TExtractor::FindDataElement( const TDataRecord& record, const TstringList& id )
{
  return FindDataElement( FindDataSegment( FindDataSection( record, id[ 0 ] ), id[ 1 ] ), id[ 2 ] );
}

Tvoid TExtractor::FillMatrix( const TDataElementList& list )
{
  switch ( theMatrixElement.GetObjectType() ) {
    case tObject1DHistogram:
      fillMatrixAs1DHistogram( list );
      break;
    case tObject2DHistogram:
      fillMatrixAs2DHistogram( list );
      break;
    case tObjectSubstituteGraph:
    case tObjectAppendGraph:
      fillMatrixAsGraph( list );
      break;
    case tObjectNtuple:
      fillMatrixAsNtuple( list );
      break;
    default:
      break;
  }
  return;
}

Tvoid TExtractor::fillMatrixAs1DHistogram( const TDataElementList& list )
{
  theFillMatrixStatus = Tfalse;

  TDataElement element = list[ 0 ];
  Tvoid* data = element.GetData();
  Telement_t type = element.GetElementType();
  Tint nevents = theMatrixElement.GetNumberOfEvents();
  Tint nprimitives = element.GetNumberOfPrimitives();

  if ( nevents != nprimitives ) {
    Tstring head = "TExtractor::fillMatrixAs1DHistogram: ";
    Tcerr << head << "size of DataElement is incompatible with MatrixElement." << Tendl;
    Tcerr << head << "#events: " << nevents << " #primitives: " << nprimitives << Tendl;
    Tcerr << head << "resize a matrix element." << Tendl;
    theMatrixElement = TMatrixElement( theMatrixElement.GetMatrixID(), theMatrixElement.GetObjectType(), nprimitives, 1 );
  }

  switch ( type ) {
    case tTypeDouble:
      for ( Tint i = 0; i < nprimitives; i ++ )
	theMatrixElement[ i ][ 0 ] = ((Tdouble*)data)[ i ];
      theFillMatrixStatus = Ttrue;
      break;
    case tTypeInt:
    case tTypeLong:
      for ( Tint i = 0; i < nprimitives; i ++ )
	theMatrixElement[ i ][ 0 ] = ((Tint*)data)[ i ];
      theFillMatrixStatus = Ttrue;
      break;
    case tTypeUnsignedShort:
      for ( Tint i = 0; i < nprimitives; i ++ )
	theMatrixElement[ i ][ 0 ] = ((TUshort*)data)[ i ];
      theFillMatrixStatus = Ttrue;
      break;
    case tTypeShort:
    case tTypeWord:
      for ( Tint i = 0; i < nprimitives; i ++ )
	theMatrixElement[ i ][ 0 ] = ((Tshort*)data)[ i ];
      theFillMatrixStatus = Ttrue;
      break;
    case tTypeFloat:
      for ( Tint i = 0; i < nprimitives; i ++ )
	theMatrixElement[ i ][ 0 ] = ((Tfloat*)data)[ i ];
      theFillMatrixStatus = Ttrue;
      break;
    case tTypeUnsignedLong:
      for ( Tint i = 0; i < nprimitives; i ++ )
	theMatrixElement[ i ][ 0 ] = ((TUlong*)data)[ i ];
      theFillMatrixStatus = Ttrue;
      break;
    case tTypeUnknown:
    case tTypeObject:
    case tTypeString:
    default:
      break;
  }

  return;
}

Tvoid TExtractor::fillMatrixAsGraph( const TDataElementList& list )
{
  theFillMatrixStatus = Tfalse;

  TDataElement xelement = list[ 0 ];
  TDataElement yelement = list[ 1 ];

  Tvoid* xdata = xelement.GetData();
  Tvoid* ydata = yelement.GetData();

  Telement_t xtype = xelement.GetElementType();
  Telement_t ytype = yelement.GetElementType();
  Tint nevents = theMatrixElement.GetNumberOfEvents();

  Tint xnprimitives = xelement.GetNumberOfPrimitives();
  Tint ynprimitives = yelement.GetNumberOfPrimitives();

  Tstring head = "TExtractor::fillMatrixAsGraph: ";

  if ( xnprimitives != ynprimitives ) {
    Tcerr << head << "number of horizontal elements is incompatible with vertical." << Tendl;
    Tcerr << head << "nothing to do, return." << Tendl;
    return;
  }

  if ( nevents != xnprimitives ) {
    Tcerr << head << "size of DataElement is incompatible with MatrixElement." << Tendl;
    Tcerr << head << "resize a matrix element." << Tendl;
    theMatrixElement = TMatrixElement( theMatrixElement.GetMatrixID(), theMatrixElement.GetObjectType(), xnprimitives, 2 );
  }

  switch ( xtype ) {
    case tTypeDouble:
      for ( Tint i = 0; i < xnprimitives; i ++ )
	theMatrixElement[ i ][ 0 ] = ((Tdouble*)xdata)[ i ];
      break;
    case tTypeInt:
    case tTypeLong:
      for ( Tint i = 0; i < xnprimitives; i ++ )
	theMatrixElement[ i ][ 0 ] = ((Tint*)xdata)[ i ];
      break;
    case tTypeUnsignedShort:
      for ( Tint i = 0; i < xnprimitives; i ++ )
	theMatrixElement[ i ][ 0 ] = ((TUshort*)xdata)[ i ];
      break;
    case tTypeShort:
    case tTypeWord:
      for ( Tint i = 0; i < xnprimitives; i ++ )
	theMatrixElement[ i ][ 0 ] = ((Tshort*)xdata)[ i ];
      break;
    case tTypeFloat:
      for ( Tint i = 0; i < xnprimitives; i ++ )
	theMatrixElement[ i ][ 0 ] = ((Tfloat*)xdata)[ i ];
      break;
    case tTypeUnsignedLong:
      for ( Tint i = 0; i < xnprimitives; i ++ )
	theMatrixElement[ i ][ 0 ] = ((TUlong*)xdata)[ i ];
      break;
    case tTypeUnknown:
    case tTypeObject:
    case tTypeString:
    default:
      break;
  }

  switch ( ytype ) {
    case tTypeDouble:
      for ( Tint i = 0; i < ynprimitives; i ++ )
	theMatrixElement[ i ][ 1 ] = ((Tdouble*)ydata)[ i ];
      theFillMatrixStatus = Ttrue;
      break;
    case tTypeInt:
    case tTypeLong:
      for ( Tint i = 0; i < ynprimitives; i ++ )
	theMatrixElement[ i ][ 1 ] = ((Tint*)ydata)[ i ];
      theFillMatrixStatus = Ttrue;
      break;
    case tTypeUnsignedShort:
      for ( Tint i = 0; i < ynprimitives; i ++ )
	theMatrixElement[ i ][ 1 ] = ((TUshort*)ydata)[ i ];
      theFillMatrixStatus = Ttrue;
      break;
    case tTypeShort:
    case tTypeWord:
      for ( Tint i = 0; i < ynprimitives; i ++ )
	theMatrixElement[ i ][ 1 ] = ((Tshort*)ydata)[ i ];
      theFillMatrixStatus = Ttrue;
      break;
    case tTypeFloat:
      for ( Tint i = 0; i < ynprimitives; i ++ )
	theMatrixElement[ i ][ 1 ] = ((Tfloat*)ydata)[ i ];
      theFillMatrixStatus = Ttrue;
      break;
    case tTypeUnsignedLong:
      for ( Tint i = 0; i < ynprimitives; i ++ )
	theMatrixElement[ i ][ 1 ] = ((TUlong*)ydata)[ i ];
      theFillMatrixStatus = Ttrue;
      break;
    case tTypeUnknown:
    case tTypeObject:
    case tTypeString:
    default:
      break;
  }

  return;
}

Tvoid TExtractor::fillMatrixAs2DHistogram( const TDataElementList& list )
{
  theFillMatrixStatus = Tfalse;

  TDataElement xelement = list[ 0 ];
  TDataElement yelement = list[ 1 ];

  Tvoid* xdata = xelement.GetData();
  Tvoid* ydata = yelement.GetData();

  Telement_t xtype = xelement.GetElementType();
  Telement_t ytype = yelement.GetElementType();
  Tint nevents = theMatrixElement.GetNumberOfEvents();

  Tint xnprimitives = xelement.GetNumberOfPrimitives();
  Tint ynprimitives = yelement.GetNumberOfPrimitives();

  Tstring head = "TExtractor::fillMatrixAs2DHistogram: ";

  if ( xnprimitives != ynprimitives ) {
    Tcerr << head << "number of horizontal elements is incompatible with vertical." << Tendl;
    Tcerr << head << "nothing to do, return." << Tendl;
    return;
  }

  if ( nevents != xnprimitives ) {
    Tcerr << head << "size of DataElement is incompatible with MatrixElement." << Tendl;
    Tcerr << head << "resize a matrix element." << Tendl;
    theMatrixElement = TMatrixElement( theMatrixElement.GetMatrixID(), theMatrixElement.GetObjectType(), xnprimitives, 2 );
  }

  switch ( xtype ) {
    case tTypeDouble:
      for ( Tint i = 0; i < xnprimitives; i ++ )
	theMatrixElement[ i ][ 0 ] = ((Tdouble*)xdata)[ i ];
      break;
    case tTypeInt:
    case tTypeLong:
      for ( Tint i = 0; i < xnprimitives; i ++ )
	theMatrixElement[ i ][ 0 ] = ((Tint*)xdata)[ i ];
      break;
    case tTypeUnsignedShort:
      for ( Tint i = 0; i < xnprimitives; i ++ )
	theMatrixElement[ i ][ 0 ] = ((TUshort*)xdata)[ i ];
      break;
    case tTypeShort:
    case tTypeWord:
      for ( Tint i = 0; i < xnprimitives; i ++ )
	theMatrixElement[ i ][ 0 ] = ((Tshort*)xdata)[ i ];
      break;
    case tTypeFloat:
      for ( Tint i = 0; i < xnprimitives; i ++ )
	theMatrixElement[ i ][ 0 ] = ((Tfloat*)xdata)[ i ];
      break;
    case tTypeUnsignedLong:
      for ( Tint i = 0; i < xnprimitives; i ++ )
	theMatrixElement[ i ][ 0 ] = ((TUlong*)xdata)[ i ];
      break;
    case tTypeUnknown:
    case tTypeObject:
    case tTypeString:
    default:
      break;
  }

  switch ( ytype ) {
    case tTypeDouble:
      for ( Tint i = 0; i < ynprimitives; i ++ )
	theMatrixElement[ i ][ 1 ] = ((Tdouble*)ydata)[ i ];
      theFillMatrixStatus = Ttrue;
      break;
    case tTypeInt:
    case tTypeLong:
      for ( Tint i = 0; i < ynprimitives; i ++ )
	theMatrixElement[ i ][ 1 ] = ((Tint*)ydata)[ i ];
      theFillMatrixStatus = Ttrue;
      break;
    case tTypeUnsignedShort:
      for ( Tint i = 0; i < ynprimitives; i ++ )
	theMatrixElement[ i ][ 1 ] = ((TUshort*)ydata)[ i ];
      theFillMatrixStatus = Ttrue;
      break;
    case tTypeShort:
    case tTypeWord:
      for ( Tint i = 0; i < ynprimitives; i ++ )
	theMatrixElement[ i ][ 1 ] = ((Tshort*)ydata)[ i ];
      theFillMatrixStatus = Ttrue;
      break;
    case tTypeFloat:
      for ( Tint i = 0; i < ynprimitives; i ++ )
	theMatrixElement[ i ][ 1 ] = ((Tfloat*)ydata)[ i ];
      theFillMatrixStatus = Ttrue;
      break;
    case tTypeUnsignedLong:
      for ( Tint i = 0; i < ynprimitives; i ++ )
	theMatrixElement[ i ][ 1 ] = ((TUlong*)ydata)[ i ];
      theFillMatrixStatus = Ttrue;
      break;
    case tTypeUnknown:
    case tTypeObject:
    case tTypeString:
    default:
      break;
  }

  return;
}

Tvoid TExtractor::fillMatrixAsNtuple( const TDataElementList& list )
{
  Tcout << "TExtractor::fillMatrixAsNtuple: under construction." << Tendl;
  return;
}

#ifdef __CLDAQ_ROOT_DLL
    ClassImp(TExtractor)
#endif
