/*! \file GeneralizedHW.hpp
\brief Generalized Hull-White model
*/

#ifndef quantlib_GeneralizedHW_hpp
#define quantlib_GeneralizedHW_hpp

#include <ql/models/shortrate/onefactormodel.hpp>
#include "..\generalizedOUprocess.hpp"


namespace QuantLib {


	//! Generalized Hull-White model class.
	/*! This class implements the standard Black-Karasinski model defined by
	\f[
	d f(r_t) = (\theta(t) - \alpha f(r_t))dt + \sigma dW_t,
	\f]
	where \f$ alpha \f$ and \f$ sigma \f$ are piecewise linear functions.

	\ingroup shortrate
	*/
	
	class GeneralizedHW : public OneFactorModel,
		public TermStructureConsistentModel {

			// TO DO: Build your fInverse class according to your model. The template class T
			// should overload the () operator to return a function value, f inverse.

	public:

		GeneralizedHW(const Handle<YieldTermStructure>& yieldtermStructure,
			const std::vector<Date>& speedstructure,
			const std::vector<Date>& volstructure);

		GeneralizedHW(const Handle<YieldTermStructure>& yieldtermStructure,
			const std::vector<Date>& speedstructure,
			const std::vector<Date>& volstructure,
			const std::vector<Real>& speed,
			const std::vector<Real>& vol);

		boost::shared_ptr<ShortRateDynamics> dynamics() const {
			QL_FAIL("no defined process for generalized Hull-White model");
		} 

		boost::shared_ptr<Lattice> tree(const TimeGrid& grid)const;


	private:

		class Dynamics;
		class Helper;
	
		std::vector<Date> speedstructure_;
		std::vector<Date> volstructure_;

		Handle<YieldTermStructure> speed() const;
		Handle<YieldTermStructure> vol() const;

		Parameter& a_;
		Parameter& sigma_;
		Parameter phi_;

	};

	//! Short-rate dynamics in the generalized Hull-White model
	/*! The short-rate is here

	f(r_t) = x_t + g(t)

	where g is the deterministic time-dependent
	parameter (which can not be determined analytically)
	used for term-structure fitting and  x_t is the state
	variable following an Ornstein-Uhlenbeck process.
	*/

	class GeneralizedHW::Dynamics : public GeneralizedHW::ShortRateDynamics {
	public:
		Dynamics(const Parameter& fitting, const Handle<YieldTermStructure>& alpha,
			const Handle<YieldTermStructure>& sigma)
			: ShortRateDynamics(boost::shared_ptr<StochasticProcess1D>(
			new GeneralizedOUprocess(alpha, sigma))), fitting_(fitting) {}

		Real variable(Time t, Rate r) const {
			return std::log(r) - fitting_(t);
		}

		Real shortRate(Time t, Real x) const {
			return std::exp(x + fitting_(t));
		}
	
	private:
		Parameter fitting_;	
	};

}


#endif

