/* $Id: TestPreprocessor.C,v 1.8 2006/12/18 08:08:49 jgrosseo Exp $ */

// This class runs the test preprocessor
// It uses AliTestShuttle to simulate a full Shuttle process

// The input data is created in the functions
//   CreateDCSAliasMap() creates input that would in the same way come from DCS
//   ReadDCSAliasMap() reads from a file
//   CreateInputFilesMap() creates a list of local files, that can be accessed by the shuttle

void TestSPDPreprocessorPhysics()
{
  // load library
  gSystem->Load("$ALICE_ROOT/SHUTTLE/TestShuttle/libTestShuttle.so");

  //  TString testShuttleDir = Form("%s/SHUTTLE/TestShuttle",getenv("ALICE_ROOT"));
  TString testShuttleDir = Form("%s/TestSPDPreprocessor",getenv("HOME"));
  TString ocdbDir = Form("local://%s/TestCDB",testShuttleDir.Data());
  TString refDir = Form("local://%s/TestReference",testShuttleDir.Data());

  // create AliTestShuttle instance
  Int_t runNr = 999;
  // The parameters are run, startTime, endTime
  AliTestShuttle* shuttle = new AliTestShuttle(runNr, 0, 1);

  // TODO if needed, change location of OCDB and Reference test folders
  // by default they are set to $ALICE_ROOT/SHUTTLE/TestShuttle/TestCDB and TestReference
  AliTestShuttle::SetMainCDB(ocdbDir.Data());
  AliTestShuttle::SetMainRefStorage(refDir.Data());
  AliTestShuttle::SetLocalRefStorage(refDir.Data());

  printf("Test OCDB storage Uri: %s\n", AliShuttleInterface::GetMainCDB().Data());
  printf("Test Reference storage Uri: %s\n", AliShuttleInterface::GetMainRefStorage().Data());


  AliITSOnlineCalibrationSPDhandler *fromOCDB_before = new AliITSOnlineCalibrationSPDhandler();

  AliCDBEntry* chkEntry = AliCDBManager::Instance()->GetStorage(AliShuttleInterface::GetMainCDB())
    ->Get("ITS/Calib/SPDNoisy", runNr);
  if (!chkEntry) {
    printf("The file is not there. Something went wrong.\n");
    return;
  }
  TObjArray* spdEntry = (TObjArray*)chkEntry->GetObject();
  fromOCDB_before->ReadNoisyFromCalibObj(spdEntry);



////  // TODO if needed, change location of temp and log folders (however they are not explicitly used here)
////  // by default they are set to $ALICE_ROOT/SHUTTLE/TestShuttle/temp and log
////  AliShuttleInterface::SetShuttleTempDir("$ALICE_ROOT/SHUTTLE/TestShuttle/temp");
////  AliShuttleInterface::SetShuttleLogDir("$ALICE_ROOT/SHUTTLE/TestShuttle/log");
////
////  printf("Test Shuttle temp dir: %s\n", AliShuttleInterface::GetShuttleTempDir());
////  printf("Test Shuttle log dir: %s\n", AliShuttleInterface::GetShuttleLogDir());


  // TODO(1)
  //
  // The shuttle can read DCS data, if the preprocessor should be tested to process DCS data,
  // some fake data has to be created.
  //
  // The "fake" input data can be taken using either (a) or (b):
  // (a) data from a file: Use ReadDCSAliasMap()
  //     the format of the file is explained in ReadDCSAliasMap()
  //     To use it uncomment the following line:
  //
  //TMap* dcsAliasMap = ReadDCSAliasMap();
  //
  // (b) generated in this macro: Use CreateDCSAliasMap() and its documentation
  //     To use it uncomment the following line:
  //
  TMap* dcsAliasMap = CreateDCSAliasMap();

  // now give the alias map to the shuttle
  shuttle->SetDCSInput(dcsAliasMap);


  // TODO(2)
  //
  // The shuttle can also process files that originate from DCS, DAQ and HLT.
  // To test it, we provide some local files and locations where these would be found when
  // the online machinery would be there.
  // In real life this functions would be produces by the sub-detectors
  // calibration programs in DCS, DAQ or HLT. These files can then be retrieved using the Shuttle.
  //
  // Files are added with the function AliTestShuttle::AddInputFile. The syntax is:
  // AddInputFile(<system>, <detector>, <id>, <source>, <local-file>)
  // In this example we add a file originating from the GDC with the id PEDESTALS
  // Three files originating from different LDCs but with the same id are also added
  // Note that the test preprocessor name is TPC. The name of the detector's preprocessor must follow
  // the "online" naming convention ALICE-INT-2003-039.
  //*** reference files



  TString calibFilesDir;
  TString id;
  TString mon;
  TString inputFile;

  calibFilesDir = Form("%s/ONLINE/Run%d", testShuttleDir.Data(),runNr);
  mon = Form("MON%d",0);

  //*** ids list
  id = "SPD_id_list";
  inputFile = Form("%s/%s/FXSids_run_%d.txt",calibFilesDir.Data(),mon.Data(),runNr);
  shuttle->AddInputFile(AliTestShuttle::kDAQ, "SPD", id.Data(), mon.Data(), inputFile.Data());

  //*** phys ref N
  id = "SPD_ref_phys";
  inputFile = Form("%s/%s/ref_phys.tar",calibFilesDir.Data(),mon.Data());
  shuttle->AddInputFile(AliTestShuttle::kDAQ, "SPD", id.Data(), mon.Data(), inputFile.Data());

  //*** phys ref D
  id = "SPD_ref_phys_dead";
  inputFile = Form("%s/%s/ref_phys_dead.tar",calibFilesDir.Data(),mon.Data());
  shuttle->AddInputFile(AliTestShuttle::kDAQ, "SPD", id.Data(), mon.Data(), inputFile.Data());

  //*** phys noisy files
  id = "SPD_phys_noisy";
  inputFile = Form("%s/%s/noisy_phys.tar",calibFilesDir.Data(),mon.Data());
  shuttle->AddInputFile(AliTestShuttle::kDAQ, "SPD", id.Data(), mon.Data(), inputFile.Data());

  //*** phys dead files
  id = "SPD_phys_dead";
  inputFile = Form("%s/%s/dead_phys.tar",calibFilesDir.Data(),mon.Data());
  shuttle->AddInputFile(AliTestShuttle::kDAQ, "SPD", id.Data(), mon.Data(), inputFile.Data());

// OLD CODE UNTARED
//  //*** phys ref N
//  for (UInt_t eq=0; eq<20; eq++) {
//    id = Form("SPD_ref_phys_%d",eq);
//    TString mon = Form("MON%d",0);
//    TString inputFile = Form("%s/ONLINE/Run%d/%s/SPDphys_run_%d_eq_%d.root",
//			     testShuttleDir.Data(),runNr,mon.Data(),runNr,eq);
//    shuttle->AddInputFile(AliTestShuttle::kDAQ, "SPD", id.Data(), mon.Data(), inputFile.Data());
//  }
//  //*** phys ref D
//  for (UInt_t eq=0; eq<20; eq++) {
//    id = Form("SPD_ref_phys_dead_%d",eq);
//    TString mon = Form("MON%d",0);
//    TString inputFile = Form("%s/ONLINE/Run%d/%s/SPDphys_dead_run_%d_%d_eq_%d.root",
//			     testShuttleDir.Data(),runNr,mon.Data(),runNr-3,runNr,eq);
//    shuttle->AddInputFile(AliTestShuttle::kDAQ, "SPD", id.Data(), mon.Data(), inputFile.Data());
//  }




  // TODO(3)
  //
  // The shuttle can read run type stored in the DAQ logbook.
  // To test it, we must provide the run type manually. They will be retrieved in the preprocessor
  // using GetRunType function.
  shuttle->SetInputRunType("PHYSICS");

  // TODO(4)
  //
  // The shuttle can read run parameters stored in the DAQ run logbook.
  // To test it, we must provide the run parameters manually. They will be retrieved in the preprocessor
  // using GetRunParameter function.
////  shuttle->AddInputRunParameter("totalEvents", "30000");
////  shuttle->AddInputRunParameter("NumberOfGDCs", "15");
  Char_t inputRunNr[10];
  sprintf(inputRunNr,"%d",runNr);
  shuttle->AddInputRunParameter("run", inputRunNr);

  // TODO(5)
  //
  // The shuttle can query condition parameters valid from the current run from the OCDB
  // To test it, we must first store the object into the OCDB. It will be retrieved in the preprocessor
  // using GetFromOCDB function.
////  TObjString obj("This is a condition parameter stored in OCDB");
////  AliCDBId id("TPC/Calib/Data", 0, AliCDBRunRange::Infinity());
////  AliCDBMetaData md;
////  AliCDBEntry entry(&obj, id, &md);
////
////  shuttle->AddInputCDBEntry(&entry);

  // TODO(6)
  // Create the preprocessor that should be tested, it registers itself automatically to the shuttle
  new AliITSPreprocessorSPD(shuttle);

  // Test the preprocessor
  shuttle->Process();

  // TODO(7)
  // In the preprocessor AliShuttleInterface::Store should be called to put the final
  // data to the CDB. To check if all went fine have a look at the files produced in
  // $ALICE_ROOT/SHUTTLE/TestShuttle/TestCDB/<detector>/SHUTTLE/Data
  //

  // Check the content of the files which should have been created
  AliITSOnlineCalibrationSPDhandler *fromFXS  = new AliITSOnlineCalibrationSPDhandler();
  fromFXS->SetFileLocation(".");
  fromFXS->ReadFromFiles();
  fromFXS->AddNoisyFrom(fromOCDB_before);

  AliITSOnlineCalibrationSPDhandler *fromOCDB = new AliITSOnlineCalibrationSPDhandler();

  AliCDBEntry* chkEntryNoisy = AliCDBManager::Instance()->GetStorage(AliShuttleInterface::GetMainCDB())
    ->Get("ITS/Calib/SPDNoisy", runNr);
  if (!chkEntryNoisy) {
    printf("Noisy file is not there. Something went wrong.\n");
    return;
  }
  TObjArray* spdEntryNoisy = (TObjArray*)chkEntryNoisy->GetObject();
  fromOCDB->ReadNoisyFromCalibObj(spdEntryNoisy);

  AliCDBEntry* chkEntryDead = AliCDBManager::Instance()->GetStorage(AliShuttleInterface::GetMainCDB())
    ->Get("ITS/Calib/SPDDead", runNr);
  if (!chkEntryDead) {
    printf("Dead file is not there. Something went wrong.\n");
    return;
  }
  TObjArray* spdEntryDead = (TObjArray*)chkEntryDead->GetObject();
  fromOCDB->ReadDeadFromCalibObj(spdEntryDead);

  if ( fromOCDB->GetNrDiff(fromFXS)==0 && fromFXS->GetNrDiff(fromOCDB)==0 ) {
    printf("OCDB update was sussessful!\n");
  }
  else {
    printf("OCDB lists and FXS lists are different!\n");
  }

  delete fromFXS;
  delete fromOCDB;
  delete fromOCDB_before;

}

TMap* CreateDCSAliasMap()
{
  // Creates a DCS structure
  // The structure is the following:
  //   TMap (key --> value)
  //     <DCSAlias> --> <valueList>
  //     <DCSAlias> is a string
  //     <valueList> is a TObjArray of AliDCSValue
  //     An AliDCSValue consists of timestamp and a value in form of a AliSimpleValue

  // In this example 6 aliases exists: DCSAlias1 ... DCSAlias6
  // Each contains 1000 values randomly generated by TRandom::Gaus + 5*nAlias

  TMap* aliasMap = new TMap;
  aliasMap->SetOwner(1);

  TRandom random;

  for(int nAlias=0;nAlias<6;nAlias++)
  {
    TObjArray* valueSet = new TObjArray;
    valueSet->SetOwner(1);

    TString aliasName="DCSAlias";
    aliasName += nAlias;
    //printf("\n\n alias: %s\n\n",aliasName.Data());

    for (int timeStamp=0;timeStamp<1000;timeStamp+=10)
    {
      AliDCSValue* dcsVal = new AliDCSValue((Float_t) (random.Gaus()+5*nAlias), timeStamp);
      //printf("%s\n",dcsVal->ToString().Data());
      valueSet->Add(dcsVal);
    }
    aliasMap->Add(new TObjString(aliasName), valueSet);
  }

  return aliasMap;
}

TMap* ReadDCSAliasMap()
{
  // Open a file that contains DCS input data
  // The CDB framework is used to open the file, this means the file is located
  // in $ALICE_ROOT/SHUTTLE/TestShuttle/TestCDB/<detector>/DCS/Data
  // The file contains an AliCDBEntry that contains a TMap with the DCS structure.
  // An explanation of the structure can be found in CreateDCSAliasMap()

  AliCDBManager::Instance()->GetStorage(AliShuttleInterface::GetMainCDB())
  AliCDBEntry *entry = AliCDBManager::Instance()->GetStorage(AliShuttleInterface::GetMainCDB())
  			->Get("DET/DCS/Data", 0);
  return dynamic_cast<TMap*> (entry->GetObject());
}

void WriteDCSAliasMap()
{
  // This writes the output from CreateDCSAliasMap to a CDB file

  TMap* dcsAliasMap = CreateDCSAliasMap();

  AliCDBMetaData metaData;
	metaData.SetBeamPeriod(0);
	metaData.SetResponsible("Responsible person");
	metaData.SetComment("Test object for TestPreprocessor.C");

  AliCDBId id("DET/DCS/Data", 0, 0);

  // look into CDB main folder

  AliCDBManager::Instance()->GetStorage(AliShuttleInterface::GetMainCDB())
  			->Put(dcsAliasMap, id, &metaData);
}
