#ifndef __FILE_LIBMLE_BASE_H_SEEN__
#define __FILE_LIBMLE_BASE_H_SEEN__ 

/* ----------------------------------------------------------------------------

Copyright (C) 2013.

A. Ronald Gallant

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program 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 General Public License for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

-----------------------------------------------------------------------------*/

#include "libscl.h" 

namespace libmle {

class usrmod_base {
public:
  virtual INTEGER len_rho() = 0;
  virtual INTEGER len_stats() = 0;
  virtual bool get_stats(scl::realmat& stats) = 0; 
  virtual void get_rho(scl::realmat& rho) = 0;
  virtual void set_rho(const scl::realmat& rho) = 0;
  virtual void set_rho_old(const scl::realmat& rho) { return; }
  virtual bool support(const scl::realmat& rho) = 0;
  virtual scl::den_val prior(const scl::realmat& rho, 
    const scl::realmat& stats) = 0;
  virtual scl::den_val likelihood() = 0; 
  virtual bool get_scores(scl::realmat& scores)
    {scl::error("Error, usrmod_base, get_scores"); return false;}
  virtual void write_usrvar(const char* filename) { return; }
  virtual ~usrmod_base() {}
};                                                
  
struct prop_group {
  REAL    freq;        // Relative probability of choosing this group
  scl::intvec  gvec;   // Contains indexes of group memebers 
  scl::realmat ginc;   // Increment of group, (fractional) power of two.
  scl::realmat mean;   // Mean vector of group, not used by r.w. props.
  scl::realmat Vmat;   // Variance matrix of group
  prop_group() : freq(1), gvec(), mean(), Vmat() { }
  prop_group(REAL f, const scl::intvec& gv, const scl::realmat& gi,
    const scl::realmat& u, const scl::realmat& V)
    : freq(f), gvec(gv), ginc(gi), mean(u), Vmat(V) { }
};

typedef std::vector<prop_group> prop_def;

class proposal_base {
public:
  virtual scl::den_val operator()(const scl::realmat& th_old, 
    const scl::realmat& th_new)=0;
  virtual void draw(INT_32BIT& seed, const scl::realmat& th_old,
    scl::realmat& th_new)=0;
  virtual INTEGER len_rho()=0;
  virtual bool transition_is_symmetric() { return false; }
  virtual ~proposal_base() {};
};

class asymptotics_base {
public:
  virtual bool set_asymptotics(const scl::realmat& sim) = 0;
  virtual void get_asymptotics(scl::realmat& rho_hat, 
    scl::realmat& V_hat, INTEGER& n) = 0;
  virtual void get_asymptotics(scl::realmat& rho_mean, 
    scl::realmat& rho_mode, REAL& post_high, scl::realmat& I, 
    scl::realmat& invJ, scl::realmat& foc_hat, INTEGER& reps) = 0;
  virtual ~asymptotics_base() {};
};

class mcmc_base {
public:
  virtual scl::realmat draw(INT_32BIT& seed, scl::realmat& rho_start,
    scl::realmat& rho_sim, scl::realmat& stats_sim, 
    scl::realmat& pi_sim) = 0;
  virtual void set_simulation_size(INTEGER n) = 0;
  virtual void set_stride(INTEGER k) = 0;
  virtual void set_draw_from_posterior(bool from_posterior) = 0;
  virtual void set_temp(REAL temperature) = 0;
  virtual REAL get_temp() = 0;
  virtual scl::realmat get_mode() = 0;    // Returns mode of posterior
  virtual REAL get_high() = 0;    // Returns posterior at mode
  virtual ~mcmc_base() {};
};

}

#endif
