#ifndef _DQMOFFLINE_HCAL_CALOTOWERSANALYZER_H_
#define _DQMOFFLINE_HCAL_CALOTOWERSANALYZER_H_

#include "FWCore/Framework/interface/Event.h"
#include "FWCore/Framework/interface/EventSetup.h"
#include "FWCore/Framework/interface/Frameworkfwd.h"
#include "FWCore/Framework/interface/MakerMacros.h"
#include "FWCore/MessageLogger/interface/MessageLogger.h"
#include "FWCore/ParameterSet/interface/ParameterSet.h"
#include "FWCore/PluginManager/interface/ModuleDef.h"
#include "FWCore/Utilities/interface/ESGetToken.h"

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

#include "DataFormats/HcalDetId/interface/HcalDetId.h"
#include "DataFormats/HcalDetId/interface/HcalElectronicsId.h"
#include "DataFormats/HcalDigi/interface/HcalDigiCollections.h"
#include "Geometry/CaloGeometry/interface/CaloCellGeometry.h"
#include "Geometry/CaloGeometry/interface/CaloGeometry.h"
#include "Geometry/CaloGeometry/interface/CaloSubdetectorGeometry.h"
#include "Geometry/CaloTopology/interface/HcalTopology.h"
#include "Geometry/HcalCommonData/interface/HcalDDDRecConstants.h"
#include "Geometry/HcalTowerAlgo/interface/HcalGeometry.h"
#include "Geometry/Records/interface/HcalRecNumberingRecord.h"

#include "DataFormats/CaloTowers/interface/CaloTowerCollection.h"
#include "DataFormats/CaloTowers/interface/CaloTowerDetId.h"
#include "DataFormats/DetId/interface/DetId.h"
#include "DataFormats/Math/interface/Vector3D.h"

#include <algorithm>
#include <cmath>
#include <ostream>
#include <string>
#include <utility>
#include <vector>

class CaloTowersAnalyzer : public DQMEDAnalyzer {
public:
  CaloTowersAnalyzer(edm::ParameterSet const &conf);
  ~CaloTowersAnalyzer() override;

  void analyze(edm::Event const &, edm::EventSetup const &) override;
  void bookHistograms(DQMStore::IBooker &, edm::Run const &, edm::EventSetup const &) override;
  void dqmBeginRun(const edm::Run &, const edm::EventSetup &) override;

private:
  double dR(double eta1, double phi1, double eta2, double phi2);

  std::string outputFile_;
  std::string hcalselector_;
  std::string mc_;
  bool useAllHistos_;

  typedef math::RhoEtaPhiVector Vector;

  edm::EDGetTokenT<CaloTowerCollection> tok_towers_;
  edm::ESGetToken<HcalDDDRecConstants, HcalRecNumberingRecord> hcalDDDRecConstantsToken_;

  int isub;
  int nevent;

  int imc;

  // eta limits to calcualte MET, SET (not to include HF if not needed)
  double etaMax[3];
  double etaMin[3];

  int iphi_bins_;
  float iphi_min_, iphi_max_;

  int ieta_bins_;
  float ieta_min_, ieta_max_;

  // ieta scan
  MonitorElement *emean_vs_ieta_E;
  MonitorElement *emean_vs_ieta_H;
  MonitorElement *emean_vs_ieta_EH;

  MonitorElement *emean_vs_ieta_E1;
  MonitorElement *emean_vs_ieta_H1;
  MonitorElement *emean_vs_ieta_EH1;

  MonitorElement *Ntowers_vs_ieta;
  MonitorElement *occupancy_map;
  MonitorElement *occupancy_vs_ieta;

  // Global maps
  MonitorElement *mapEnergy_E;
  MonitorElement *mapEnergy_H;
  MonitorElement *mapEnergy_EH;
  MonitorElement *mapEnergy_N;

  // for number of bad, recovered and problematic Ecal and Hcal cells
  MonitorElement *numBadCellsEcal_EB;
  MonitorElement *numBadCellsEcal_EE;
  MonitorElement *numRcvCellsEcal_EB;
  MonitorElement *numRcvCellsEcal_EE;
  MonitorElement *numPrbCellsEcal_EB;
  MonitorElement *numPrbCellsEcal_EE;

  MonitorElement *numBadCellsHcal_HB;
  MonitorElement *numBadCellsHcal_HE;
  MonitorElement *numBadCellsHcal_HF;
  MonitorElement *numRcvCellsHcal_HB;
  MonitorElement *numRcvCellsHcal_HE;
  MonitorElement *numRcvCellsHcal_HF;
  MonitorElement *numPrbCellsHcal_HB;
  MonitorElement *numPrbCellsHcal_HE;
  MonitorElement *numPrbCellsHcal_HF;

  // HB
  MonitorElement *meEnergyHcalvsEcal_HB;
  MonitorElement *meEnergyHO_HB;
  MonitorElement *meEnergyEcal_HB;
  MonitorElement *meEnergyHcal_HB;
  MonitorElement *meNumFiredTowers_HB;

  MonitorElement *meEnergyEcalTower_HB;
  MonitorElement *meEnergyHcalTower_HB;
  MonitorElement *meTotEnergy_HB;

  MonitorElement *meIphiHcalTower_HBP;
  MonitorElement *meIphiHcalTower_HBM;

  MonitorElement *mapEnergy_HB;
  MonitorElement *mapEnergyEcal_HB;
  MonitorElement *mapEnergyHcal_HB;
  MonitorElement *MET_HB;
  MonitorElement *SET_HB;
  MonitorElement *phiMET_HB;

  MonitorElement *emTiming_HB;
  MonitorElement *hadTiming_HB;

  MonitorElement *emEnergyTiming_Low_HB;
  MonitorElement *emEnergyTiming_HB;
  MonitorElement *emEnergyTiming_High_HB;
  MonitorElement *emEnergyTiming_profile_Low_HB;
  MonitorElement *emEnergyTiming_profile_HB;
  MonitorElement *emEnergyTiming_profile_High_HB;

  MonitorElement *hadEnergyTiming_Low_HB;
  MonitorElement *hadEnergyTiming_HB;
  MonitorElement *hadEnergyTiming_High_HB;
  MonitorElement *hadEnergyTiming_profile_Low_HB;
  MonitorElement *hadEnergyTiming_profile_HB;
  MonitorElement *hadEnergyTiming_profile_High_HB;

  // HE
  MonitorElement *meEnergyHcalvsEcal_HE;
  MonitorElement *meEnergyHO_HE;
  MonitorElement *meEnergyEcal_HE;
  MonitorElement *meEnergyHcal_HE;
  MonitorElement *meNumFiredTowers_HE;

  MonitorElement *meEnergyEcalTower_HE;
  MonitorElement *meEnergyHcalTower_HE;
  MonitorElement *meTotEnergy_HE;

  MonitorElement *meIphiHcalTower_HEP;
  MonitorElement *meIphiHcalTower_HEM;

  MonitorElement *mapEnergy_HE;
  MonitorElement *mapEnergyEcal_HE;
  MonitorElement *mapEnergyHcal_HE;
  MonitorElement *MET_HE;
  MonitorElement *SET_HE;
  MonitorElement *phiMET_HE;

  MonitorElement *emTiming_HE;
  MonitorElement *hadTiming_HE;

  MonitorElement *emEnergyTiming_Low_HE;
  MonitorElement *emEnergyTiming_HE;
  MonitorElement *emEnergyTiming_profile_Low_HE;
  MonitorElement *emEnergyTiming_profile_HE;

  MonitorElement *hadEnergyTiming_Low_HE;
  MonitorElement *hadEnergyTiming_HE;
  MonitorElement *hadEnergyTiming_profile_Low_HE;
  MonitorElement *hadEnergyTiming_profile_HE;

  // HF
  MonitorElement *meEnergyHcalvsEcal_HF;
  MonitorElement *meEnergyHO_HF;
  MonitorElement *meEnergyEcal_HF;
  MonitorElement *meEnergyHcal_HF;
  MonitorElement *meNumFiredTowers_HF;

  MonitorElement *meEnergyEcalTower_HF;
  MonitorElement *meEnergyHcalTower_HF;
  MonitorElement *meTotEnergy_HF;

  MonitorElement *meIphiCaloTower_HFP;
  MonitorElement *meIphiCaloTower_HFM;

  MonitorElement *mapEnergy_HF;
  MonitorElement *mapEnergyEcal_HF;
  MonitorElement *mapEnergyHcal_HF;
  MonitorElement *MET_HF;
  MonitorElement *SET_HF;
  MonitorElement *phiMET_HF;

  MonitorElement *emTiming_HF;
  MonitorElement *hadTiming_HF;
  MonitorElement *emEnergyTiming_HF;
  MonitorElement *emEnergyTiming_profile_HF;

  MonitorElement *hadEnergyTiming_Low_HF;
  MonitorElement *hadEnergyTiming_HF;
  MonitorElement *hadEnergyTiming_profile_Low_HF;
  MonitorElement *hadEnergyTiming_profile_HF;
};

#endif
