/*  Multimodal Image Segmentation Tool (MIST)  */
/*  Eelke Visser  */

/*  Copyright (c) 2016 University of Oxford  */

/*  CCOPYRIGHT  */

#ifndef PROFILEMODEL_H
#define PROFILEMODEL_H

#include <iostream>
#include <unordered_map>
#include <vector>
#include <boost/log/trivial.hpp>
#include <stdexcept>
#include "serialisation.h"
#include "plotting.h"
#include "armawrap/newmat.h"

using namespace Plotting;

class ProfileModel
{
public:
    class ModelException : public std::logic_error
    {
    public:
        ModelException(const std::string &what) : logic_error(what) { };
    };

    ProfileModel(const std::vector<std::string> &modalitynames, int reflength, int datalength);

    // NB: Using default copy constructor / operator=

    virtual ~ProfileModel();

    virtual boost::shared_ptr<ProfileModel> Clone() const = 0;

    int GetNumberOfSteps() const;

    void SetNormalisation(const std::string &modality, double mean, double stdev);

    virtual void Train(const std::unordered_map<std::string, std::vector<NEWMAT::ColumnVector> > &trainingdata) = 0;
    virtual std::vector<double> GetDeltaLikelihoods(const std::unordered_map<std::string, NEWMAT::ColumnVector> &data,
                                                    bool usedeltaprior) const = 0;

    virtual void WritePlots(const Plotting::plotfunc &pfunc, int vertex,
                            std::unordered_map<std::string, std::vector<NEWMAT::ColumnVector> > *profiles = nullptr) const = 0;

protected:
    std::vector<std::string> m_modalityNames;
    int m_refLength;
    int m_dataLength;

    // For normalisation, should be computed over all vertices by caller
    std::unordered_map<std::string, double> m_globalMean;
    std::unordered_map<std::string, double> m_globalStdev;

private:
    friend class boost::serialization::access;

    template<class Archive>
    void serialize(Archive &ar, const unsigned int version);
};

template<class Archive>
void ProfileModel::serialize(Archive &ar, const unsigned int version)
{
    BOOST_LOG_TRIVIAL(debug) << "(De)serialising ProfileModel";
    // NB: Constructor parameters are serialised in non-virtual derived classes!
}

#endif // PROFILEMODEL_H
