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

#include "JTools/JFunction1D_t.hh"
#include "JTools/JFunctionalMap_t.hh"
#include "JPhysics/JPDFTransformer.hh"
#include "JPhysics/JPDFTable.hh"
#include "JPhysics/JPDFTypes.hh"
#include "Jeep/JPrint.hh"
#include "Jeep/JParser.hh"
#include "Jeep/JMessage.hh"


/**
 * \file
 *
 * Program to print PDF of Cherenkov light from elongated EM-shower.
 * \author mdejong
 */
int main(int argc, char **argv)
{
  using namespace std;
  using namespace JPP;

  string         inputFile;
  int            debug;

  try { 

    JParser<> zap("Program to print PDF of Cherenkov light from elongated EM-shower.");

    zap['f'] = make_field(inputFile);
    zap['d'] = make_field(debug)                                   = 2;

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


  typedef JPolint0Function1D_t                                    JFunction1D_t;
  typedef JMAPLIST<JPolint0FunctionalMap,
		   JPolint0FunctionalMap,
		   JPolint0FunctionalMap,
		   JPolint0FunctionalGridMap,
		   JPolint0FunctionalGridMap>::maplist            JMapList_t;
  typedef JPDFTable<JFunction1D_t, JMapList_t>                    JPDF_t;

  JPDF_t pdf;

  try {

    NOTICE("loading input from file " << inputFile << "... " << flush);
      
    pdf.load(inputFile.c_str());

    NOTICE("OK" << endl);
  }
  catch(const JException& error) {
    FATAL(error.what() << endl);
  }

  int number_of_counts = 0;
  int number_of_errors = 0;

  for (JPDF_t::super_const_iterator i = pdf.super_begin(); i != pdf.super_end(); ++i) {

    const JFunction1D_t& f1 = i.getValue();

    for (JFunction1D_t::const_iterator p = f1.begin(); p != f1.end(); ++p) {

      number_of_counts += 1;

      if (p->getY() != p->getY()) {

	if (debug >= debug_t) {
	  cout << FIXED(15,5) << i->first                                      << ' ';
	  cout << FIXED(15,5) << i->second->first                              << ' ';
	  cout << FIXED(15,5) << i->second->second->first                      << ' ';
	  cout << FIXED(15,5) << i->second->second->second->first              << ' ';
	  cout << FIXED(15,5) << i->second->second->second->second->first      << ' ';
	  cout << FIXED(15,5) << p->getX()                                     << ' ';
	  cout << FIXED(15,5) << p->getY()                                     << endl;
	}

	number_of_errors += 1;
      }
    }
  }

  cout << "Number of errors / counts: " << number_of_errors << " / " << number_of_counts << endl;

  if (number_of_errors != 0) {
    FATAL("Number of errors " << number_of_errors << endl);
  }

  return 0;
}