/*****************************************************************************
 * $CAMITK_LICENCE_BEGIN$
 *
 * CamiTK - Computer Assisted Medical Intervention ToolKit
 * (c) 2001-2025 Univ. Grenoble Alpes, CNRS, Grenoble INP - UGA, TIMC, 38000 Grenoble, France
 *
 * Visit http://camitk.imag.fr for more information
 *
 * This file is part of CamiTK.
 *
 * CamiTK is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * CamiTK is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with CamiTK.  If not, see <http://www.gnu.org/licenses/>.
 *
 * $CAMITK_LICENCE_END$
 ****************************************************************************/

#ifndef MONITOR_MONITOR_H
#define MONITOR_MONITOR_H

#include "MMLAPI.h"

#include <string>
#include <vector>

// Monitor includes
#include "MonitoringManager.h"
#include <MonitorIn.hxx>

// Reference includes
#include "Reference.h"
/**
 * @ingroup group_cepmodeling_libraries_mml
 *
 * @brief
 * A monitor calculate and store followed data (ex:calculation between current position and references)
 * At current time (current state of simulation is given by Parameters class)
 * A monitor is active between startAt and stopAt time
 *
 **/
class MML_API Monitor {

public:

    /**
     * type of the values stored (please update typeCount and doc if you update the enum)
     * SCALAR: the monitor store a single scalar value
     * SCALARSET: the monitor stores a scalar value for each atom
     * VECTORSET: the monitor stores 3 scalar values for each atom
     * MATRIX_33SET: the monitor stores a matrix 3x3 for each atom
     */
    enum type {
        SCALAR,
        SCALARSET,
        VECTORSET,
        MATRIX_33SET
    };
    /// number of possible types (siez of the previous enum). Please always update if the enum is updated.
    static const unsigned int typeCount = 4;

    /**
     * constructor
     * @param m the xsdcxx generated monitor
     */
    Monitor(mml::Monitor* m, MonitoringManager* monitoringManager, Monitor::type type);
    /// destructor
    virtual ~Monitor();

    /// calculate current followed data and store them in values vector
    virtual void calculate() = 0;
    /// write data stored in values vector into mmlOut file
    virtual void write();

    int getIndex();
    double getStartAt();
    double getStopAt();
    std::string getReferenceName();
    std::string getTargetName();
    Monitor::type getValueType();
    virtual std::string getTypeName() = 0;

    /// populate values with the corresponding values at index i
    bool getValuesOfIndex(int i, double values[]);
    /// get index i of indexes vector
    int getIndexOfValues(const unsigned int i);
    /// get value i of values vector
    double getValue(const unsigned int i);
    /// get number of index in indexes vetor
    unsigned int getNumberOfIndex();
    /// get number of value in values vetor
    unsigned int getNumberOfValues();

protected:
    /// index of monitor
    int index;
    /// time to start monitoring
    double startAt;
    /// time to stop monitoring
    double stopAt;
    /// references used when monitor need references
    std::vector<Reference*> references;
    /// the name of the component targeted by the monitor
    std::string target;
    /// map between indexes and values
    std::map<int, std::vector<double> > indexToValuesMap;
    /// the xsdcxx object representing monitor, used for serialization
    mml::Monitor* mappedObject;
    /// monitoring manager
    MonitoringManager* monitoringManager;
    /// type of the values stored
    Monitor::type valueType;
    /// dimension of data stored
    int dimension;
    /// offset in x direction (if reference is not aligned)
    double dx;
    /// offset in y direction (if reference is not aligned)
    double dy;
    /// offset in z direction (if reference is not aligned)
    double dz;
    /// the vector which contains data monitored
    std::vector<double> values;
    /// vector which contains target's atoms index (in same order that values associate with)
    std::vector<int> indexes;
};

#endif // MONITOR_MONITOR_H

