#include <string>
#include <iostream>
#include <iomanip>

#include "JDetector/JDetector.hh"
#include "JDetector/JDetectorToolkit.hh"
#include "JDetector/JModuleRouter.hh"
#include "JDetector/JDetectorAddressMapToolkit.hh"
#include "JDetector/JModuleGeometry.hh"
#include "JIO/JFileStreamIO.hh"

#include "Jeep/JParser.hh"
#include "Jeep/JMessage.hh"
#include "Jeep/JTimer.hh"


/**
 * \file
 *
 * Program to convert ntuples to detector.
 * \author mdejong
 */
int main(int argc, char **argv)
{
  using namespace std;

  string         detectorFile;
  string         ntupleFile;
  string         outputFile;
  int            debug;

  try {

    JParser<> zap("Program to convert ntuples to detector.");

    zap['a'] = make_field(detectorFile);
    zap['f'] = make_field(ntupleFile);
    zap['o'] = make_field(outputFile)  = "";
    zap['d'] = make_field(debug)       = 0;

    zap(argc, argv);
  }
  catch(const exception &error) {
    FATAL(error.what() << endl);
  }

  
  using namespace JPP;


  JDetector detector;

  try {
    load(detectorFile, detector);
  }
  catch(const JException& error) {
    FATAL(error);
  }


  const JModuleRouter        router(detector);
  const JDetectorAddressMap& demo = getDetectorAddressMap(detector.getID());

  
  JTimer timer("module");

  JFileStreamReader in(ntupleFile.c_str());

  for (JModuleGeometry geometry; in.load(geometry); ) {

    DEBUG(geometry << endl);
    
    const int id = geometry.getID();

    if (router.hasModule(id)) {

      timer.start();

      const JEulerMatrix3D R(geometry.getEulerAngle());
      
      JModule master = getModule(demo.get(id), id);
      
      master.rotate(R);
      master.add(geometry.getPosition());
   
      JModule& module = detector.getModule(router.getAddress(id)); 
   
      if (module.size() == master.size()) {

	for (int pmt = 0; pmt != (int) master.size(); ++pmt) {
	  module.getPMT(pmt).setAxis(master.getPMT(pmt).getAxis());
	}

	module.compile();

      } else {

	ERROR("Module sizes inconsistent " << module.size() << " != " << master.size() << endl);
      }

      timer.stop();

    } else {
      
      ERROR("Missing module " << geometry.getID() << endl);
    }
  }

  in.close();

  timer.print(cout);

  if (outputFile != "") {

    if (outputFile == "%") {
      outputFile = detectorFile;
    }

    try {
      store(outputFile, detector);
    }
    catch(const JException& error) {
      FATAL(error);
    }
  }
}