// -*- C++ -*-
//
// Package:    V0Validator
// Class:      V0Validator
//
/**\class V0Validator V0Validator.cc
 Validation/RecoVertex/interface/V0Validator.h

 Description: Creates validation histograms for RecoVertex/V0Producer

 Implementation:
     <Notes on implementation>
*/
//
// Original Author:  Brian Drell
//         Created:  Wed Feb 18 17:21:04 MST 2009
//
//

// system include files
#include <memory>
#include <array>

// user include files
#include "FWCore/Framework/interface/Frameworkfwd.h"

#include "FWCore/Framework/interface/Event.h"
#include "FWCore/Framework/interface/MakerMacros.h"

#include "FWCore/ParameterSet/interface/ParameterSet.h"
#include "FWCore/ServiceRegistry/interface/Service.h"
#include "CommonTools/UtilAlgos/interface/TFileService.h"

#include "DQMServices/Core/interface/DQMStore.h"
#include "DQMServices/Core/interface/DQMEDAnalyzer.h"

#include "FWCore/ServiceRegistry/interface/Service.h"

#include "DataFormats/TrackReco/interface/Track.h"
#include "DataFormats/TrackReco/interface/TrackFwd.h"
#include "SimDataFormats/Track/interface/SimTrackContainer.h"
#include "SimDataFormats/Vertex/interface/SimVertexContainer.h"
#include "SimTracker/TrackerHitAssociation/interface/TrackerHitAssociator.h"
#include "SimDataFormats/TrackingAnalysis/interface/TrackingParticle.h"
#include "SimDataFormats/TrackingAnalysis/interface/TrackingVertex.h"
#include "TrackingTools/TrajectoryState/interface/FreeTrajectoryState.h"
#include "TrackingTools/PatternTools/interface/TrajectoryStateClosestToBeamLineBuilder.h"
#include "TrackingTools/PatternTools/interface/ClosestApproachInRPhi.h"

#include "DataFormats/Candidate/interface/Candidate.h"
#include "DataFormats/Candidate/interface/VertexCompositeCandidate.h"
#include "DataFormats/V0Candidate/interface/V0Candidate.h"
#include "DataFormats/RecoCandidate/interface/RecoChargedCandidate.h"

#include "SimTracker/TrackHistory/interface/TrackClassifier.h"
#include "SimDataFormats/TrackingAnalysis/interface/TrackingParticleFwd.h"

#include "Geometry/CommonDetUnit/interface/TrackingGeometry.h"
#include "Geometry/TrackerGeometryBuilder/interface/TrackerGeometry.h"
#include "Geometry/Records/interface/TrackerDigiGeometryRecord.h"
#include "Geometry/CommonDetUnit/interface/GeomDet.h"
#include "Geometry/CommonDetUnit/interface/GluedGeomDet.h"

#include "MagneticField/Records/interface/IdealMagneticFieldRecord.h"
#include "MagneticField/VolumeBasedEngine/interface/VolumeBasedMagneticField.h"

#include "RecoVertex/VertexTools/interface/VertexDistance3D.h"
#include "DataFormats/VertexReco/interface/Vertex.h"

#include "HepMC/GenVertex.h"
#include "HepMC/GenParticle.h"

#include "TROOT.h"
#include "TMath.h"
#include "TH1F.h"
#include "TH1I.h"
#include "TH2F.h"

class V0Validator : public DQMEDAnalyzer {
public:
  explicit V0Validator(const edm::ParameterSet &);
  ~V0Validator() override;
  enum V0Type { KSHORT, LAMBDA };
  struct V0Couple {
    reco::TrackRef one;
    reco::TrackRef two;
    explicit V0Couple(reco::TrackRef first_daughter, reco::TrackRef second_daughter) {
      one = first_daughter.key() < second_daughter.key() ? first_daughter : second_daughter;
      two = first_daughter.key() > second_daughter.key() ? first_daughter : second_daughter;
      assert(one != two);
    }
    bool operator<(const V0Couple &rh) const { return one.key() < rh.one.key(); }
    bool operator==(const V0Couple &rh) const { return ((one.key() == rh.one.key()) && (two.key() == rh.two.key())); }
  };

private:
  void analyze(const edm::Event &, const edm::EventSetup &) override;
  void bookHistograms(DQMStore::IBooker &, edm::Run const &, edm::EventSetup const &) override;
  void doFakeRates(const reco::VertexCompositeCandidateCollection &collection,
                   const reco::RecoToSimCollection &recotosimCollection,
                   V0Type t,
                   int particle_pdgid,
                   int misreconstructed_particle_pdgid);

  void doEfficiencies(const TrackingVertexCollection &gen_vertices,
                      V0Type t,
                      int parent_particle_id,
                      int first_daughter_id,  /* give only positive charge */
                      int second_daughter_id, /* give only positive charge */
                      const reco::VertexCompositeCandidateCollection &collection,
                      const reco::SimToRecoCollection &simtorecoCollection);

  // MonitorElements for final histograms

  std::array<MonitorElement *, 2> candidateEffVsR_num_;
  std::array<MonitorElement *, 2> candidateEffVsEta_num_;
  std::array<MonitorElement *, 2> candidateEffVsPt_num_;
  std::array<MonitorElement *, 2> candidateTkEffVsR_num_;
  std::array<MonitorElement *, 2> candidateTkEffVsEta_num_;
  std::array<MonitorElement *, 2> candidateTkEffVsPt_num_;
  std::array<MonitorElement *, 2> candidateFakeVsR_num_;
  std::array<MonitorElement *, 2> candidateFakeVsEta_num_;
  std::array<MonitorElement *, 2> candidateFakeVsPt_num_;
  std::array<MonitorElement *, 2> candidateTkFakeVsR_num_;
  std::array<MonitorElement *, 2> candidateTkFakeVsEta_num_;
  std::array<MonitorElement *, 2> candidateTkFakeVsPt_num_;

  std::array<MonitorElement *, 2> candidateFakeVsR_denom_;
  std::array<MonitorElement *, 2> candidateFakeVsEta_denom_;
  std::array<MonitorElement *, 2> candidateFakeVsPt_denom_;
  std::array<MonitorElement *, 2> candidateEffVsR_denom_;
  std::array<MonitorElement *, 2> candidateEffVsEta_denom_;
  std::array<MonitorElement *, 2> candidateEffVsPt_denom_;

  std::array<MonitorElement *, 2> nCandidates_;
  std::array<MonitorElement *, 2> candidateStatus_;
  std::array<MonitorElement *, 2> fakeCandidateMass_;
  std::array<MonitorElement *, 2> candidateFakeDauRadDist_;
  std::array<MonitorElement *, 2> candidateMassAll;
  std::array<MonitorElement *, 2> goodCandidateMass;

  std::string theDQMRootFileName;
  std::string dirName;
  edm::EDGetTokenT<reco::RecoToSimCollection> recoRecoToSimCollectionToken_;
  edm::EDGetTokenT<reco::SimToRecoCollection> recoSimToRecoCollectionToken_;
  edm::EDGetTokenT<TrackingVertexCollection> trackingVertexCollection_Token_;
  edm::EDGetTokenT<std::vector<reco::Vertex> > vec_recoVertex_Token_;
  edm::EDGetTokenT<reco::VertexCompositeCandidateCollection> recoVertexCompositeCandidateCollection_k0s_Token_,
      recoVertexCompositeCandidateCollection_lambda_Token_;
};
