/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */

/*
 Copyright (C) 2016 Quaternion Risk Management Ltd

 This file is part of QuantLib, a free-software/open-source library
 for financial quantitative analysts and developers - http://quantlib.org/

 QuantLib is free software: you can redistribute it and/or modify it
 under the terms of the QuantLib license.  You should have received a
 copy of the license along with this program; if not, please email
 <quantlib-dev@lists.sf.net>. The license is also available online at
 <https://www.quantlib.org/license.shtml>.

 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 license for more details.
*/

/*! \file discountingconstnotionalcrosscurrencyswapengine.hpp
    \brief Cross currency swap engine
*/

#ifndef quantlib_discounting_cross_currency_swap_engine_hpp
#define quantlib_discounting_cross_currency_swap_engine_hpp

#include <ql/handle.hpp>
#include <ql/instruments/constnotionalcrosscurrencyswap.hpp>
#include <ql/termstructures/yieldtermstructure.hpp>
#include <ql/optional.hpp>

namespace QuantLib {

//! Discounting cross-currency swap engine
/*! This class implements an engine for pricing swaps comprising legs that
    involve two currencies. The npv is expressed in domesticCcy. The given currencies
    domesticCcy and foreignCcy are matched to the correct swap legs. The evaluation date is the
    reference date of either discounting curve (which must be equal).

   \ingroup engines
*/
class DiscountingConstNotionalCrossCurrencySwapEngine : public ConstNotionalCrossCurrencySwap::engine {
  public:
    //! \name Constructors
    //@{
    /*! \param domesticCcy
               Domestic currency
        \param domesticCcyDiscountCurve
               Discount curve for cash flows in domestic currency
        \param foreignCcy
               Foreign currency
        \param foreignCcyDiscountCurve
               Discount curve for cash flows in foreign currency
        \param spotFX
               The market spot rate quote, given as units of domesticCcy
               for one unit of foreignCcy. The spot rate must be given
               w.r.t. a settlement equal to the npv date.
        \param includeSettlementDateFlows, settlementDate
               If includeSettlementDateFlows is true (false), cashflows
               on the settlementDate are (not) included in the NPV.
               If not given the settlement date is set to the
               npv date.
        \param npvDate
               Discount to this date. If not given the npv date
               is set to the evaluation date
        \param spotFXSettleDate
               FX conversion as of this date if specified explicitly
    */
    DiscountingConstNotionalCrossCurrencySwapEngine(Currency  domesticCcy, const Handle<YieldTermStructure>& domesticCcyDiscountCurve,
                       Currency  foreignCcy, const Handle<YieldTermStructure>& foreignCcyDiscountCurve,
                       const Handle<Quote>& spotFX, ext::optional<bool> includeSettlementDateFlows = ext::nullopt,
                       const Date& settlementDate = Date(), const Date& npvDate = Date(), const Date& spotFXSettleDate = Date());
    //@}

    //! \name PricingEngine interface
    //@{
    void calculate() const override;
    //@}

    //! \name Inspectors
    //@{
    const Handle<YieldTermStructure>& domesticCcyDiscountCurve() const { return domesticCcyDiscountcurve_; }
    const Handle<YieldTermStructure>& foreignCcyDiscountCurve() const { return foreignCcyDiscountcurve_; }

    const Currency& domesticCurrency() const { return domesticCcy_; }
    const Currency& foreignCurrency() const { return foreignCcy_; }

    const Handle<Quote>& spotFX() const { return spotFX_; }
    //@}

  private:
    Currency domesticCcy_;
    Handle<YieldTermStructure> domesticCcyDiscountcurve_;
    Currency foreignCcy_;
    Handle<YieldTermStructure> foreignCcyDiscountcurve_;
    Handle<Quote> spotFX_;
    ext::optional<bool> includeSettlementDateFlows_;
    Date settlementDate_;
    Date npvDate_;
    Date spotFXSettleDate_;
};

}

#endif
