//
// ********************************************************************
// * License and Disclaimer                                           *
// *                                                                  *
// * The  Geant4 software  is  copyright of the Copyright Holders  of *
// * the Geant4 Collaboration.  It is provided  under  the terms  and *
// * conditions of the Geant4 Software License,  included in the file *
// * LICENSE and available at  http://cern.ch/geant4/license .  These *
// * include a list of copyright holders.                             *
// *                                                                  *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work  make  any representation or  warranty, express or implied, *
// * regarding  this  software system or assume any liability for its *
// * use.  Please see the license in the file  LICENSE  and URL above *
// * for the full disclaimer and the limitation of liability.         *
// *                                                                  *
// * This  code  implementation is the result of  the  scientific and *
// * technical work of the GEANT4 collaboration.                      *
// * By using,  copying,  modifying or  distributing the software (or *
// * any work based  on the software)  you  agree  to acknowledge its *
// * use  in  resulting  scientific  publications,  and indicate your *
// * acceptance of all terms of the Geant4 Software license.          *
// ********************************************************************
//
// This example is provided by the Geant4-DNA collaboration
// chem6 example is derived from chem4 and chem5 examples
//
// Any report or published results obtained using the Geant4-DNA software
// shall cite the following Geant4-DNA collaboration publication:
// J. Appl. Phys. 125 (2019) 104301
// Med. Phys. 45 (2018) e722-e739
// J. Comput. Phys. 274 (2014) 841-882
// Med. Phys. 37 (2010) 4692-4708
// Int. J. Model. Simul. Sci. Comput. 1 (2010) 157-178
// The Geant4-DNA web site is available at http://geant4-dna.org
//
// Authors: W. G. Shin and S. Incerti (CENBG, France)
//
// $Id$
//
/// \file ScoreSpecies.hh
/// \brief Definition of the ScoreSpecies class

#ifndef CHEM6_ScoreSpecies_h
#define CHEM6_ScoreSpecies_h 1

#include "G4THitsMap.hh"
#include "G4UIcmdWithADoubleAndUnit.hh"
#include "G4UIcmdWithAnInteger.hh"
#include "G4UImessenger.hh"
#include "G4VPrimitiveScorer.hh"

#include <set>

class G4VAnalysisManager;
class G4MolecularConfiguration;

/** \file ScoreSpecies.hh*/

// Description:
//   This is a primitive scorer class for scoring the radiolitic species
// produced after irradiation in a water volume
//
// Created: 2015-10-27  by M. Karamitros,
// modified: 2016-03-16 by P. Piersimoni

class ScoreSpecies : public G4VPrimitiveScorer, public G4UImessenger
{
  public:
    ScoreSpecies(G4String name, G4int depth = 0);

    virtual ~ScoreSpecies();

    /** Add a time at which the number of species should be recorded.
        Default times are set up to 1 microsecond.*/
    inline void AddTimeToRecord(double time) { fTimeToRecord.insert(time); }

    /**  Remove all times to record, must be reset by user.*/
    inline void ClearTimeToRecord() { fTimeToRecord.clear(); }

    /** Get number of recorded events*/
    inline int GetNumberOfRecordedEvents() const { return fNEvent; }

    /** Write results to whatever chosen file format*/
    void WriteWithAnalysisManager(G4VAnalysisManager*);

    struct SpeciesInfo
    {
        SpeciesInfo()
        {
          fNumber = 0;
          fG = 0.;
          fG2 = 0.;
        }
        SpeciesInfo(const SpeciesInfo& right)  // Species A(B);
        {
          fNumber = right.fNumber;
          fG = right.fG;
          fG2 = right.fG2;
        }
        SpeciesInfo& operator=(const SpeciesInfo& right)  // A = B
        {
          if (&right == this) return *this;
          fNumber = right.fNumber;
          fG = right.fG;
          fG2 = right.fG2;
          return *this;
        }
        int fNumber;
        double fG;
        double fG2;
    };

  private:
    typedef const G4MolecularConfiguration Species;
    typedef std::map<Species*, SpeciesInfo> InnerSpeciesMap;
    typedef std::map<double, InnerSpeciesMap> SpeciesMap;
    SpeciesMap fSpeciesInfoPerTime;

    std::set<G4double> fTimeToRecord;

    int fNEvent;  // number of processed events
    double fEdep;  // total energy deposition
    G4String fOutputType;  // output type

  protected:
    virtual G4bool ProcessHits(G4Step*, G4TouchableHistory*);

  public:
    virtual void Initialize(G4HCofThisEvent*);
    virtual void EndOfEvent(G4HCofThisEvent*);
    virtual void DrawAll();
    virtual void PrintAll();
    /** Method used in multithreading mode in order to merge
        the results*/
    virtual void AbsorbResultsFromWorkerScorer(G4VPrimitiveScorer*);
    virtual void OutputAndClear();
    virtual void SetNewValue(G4UIcommand*, G4String);

    SpeciesMap GetSpeciesInfo() { return fSpeciesInfoPerTime; }

  private:
    G4int fHCID;
    G4THitsMap<G4double>* fEvtMap;

    G4int fRunID;
    G4UIdirectory* fSpeciesdir;
    G4UIcmdWithAnInteger* fTimeBincmd;
    G4UIcmdWithADoubleAndUnit* fAddTimeToRecordcmd;
};
#endif
