/*
 * Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies
 *
 * Please see distribution for license.
 */
package com.opengamma.strata.pricer.swap;

import com.opengamma.strata.basics.currency.MultiCurrencyAmount;
import com.opengamma.strata.market.explain.ExplainMapBuilder;
import com.opengamma.strata.market.sensitivity.PointSensitivityBuilder;
import com.opengamma.strata.pricer.impl.swap.DispatchingSwapPaymentEventPricer;
import com.opengamma.strata.pricer.rate.RatesProvider;
import com.opengamma.strata.product.swap.SwapPaymentEvent;

/**
 * Pricer for payment events.
 * <p>
 * This function provides the ability to price a {@link SwapPaymentEvent}.
 * <p>
 * Implementations must be immutable and thread-safe functions.
 * 
 * @param <T>  the type of event
 */
public interface SwapPaymentEventPricer<T extends SwapPaymentEvent> {

  /**
   * Returns the standard instance of the function.
   * <p>
   * Use this method to avoid a direct dependency on the implementation.
   * 
   * @return the payment event pricer
   */
  public static SwapPaymentEventPricer<SwapPaymentEvent> standard() {
    return DispatchingSwapPaymentEventPricer.DEFAULT;
  }

  //-------------------------------------------------------------------------
  /**
   * Calculates the present value of a single payment event.
   * <p>
   * The amount is expressed in the currency of the event.
   * This returns the value of the event with discounting.
   * <p>
   * The payment date of the event should not be in the past.
   * The result of this method for payment dates in the past is undefined.
   * 
   * @param event  the event
   * @param provider  the rates provider
   * @return the present value of the event
   */
  public abstract double presentValue(T event, RatesProvider provider);

  /**
   * Calculates the present value sensitivity of a single payment event.
   * <p>
   * The present value sensitivity of the event is the sensitivity of the present value to
   * the underlying curves.
   * 
   * @param event  the event
   * @param provider  the rates provider
   * @return the present value curve sensitivity of the event
   */
  public abstract PointSensitivityBuilder presentValueSensitivity(T event, RatesProvider provider);

  //-------------------------------------------------------------------------
  /**
   * Calculates the forecast value of a single payment event.
   * <p>
   * The amount is expressed in the currency of the event.
   * This returns the value of the event without discounting.
   * <p>
   * The payment date of the event should not be in the past.
   * The result of this method for payment dates in the past is undefined.
   * 
   * @param event  the event
   * @param provider  the rates provider
   * @return the forecast value of the event
   */
  public abstract double forecastValue(T event, RatesProvider provider);

  /**
   * Calculates the forecast value sensitivity of a single payment event.
   * <p>
   * The forecast value sensitivity of the event is the sensitivity of the forecast value to
   * the underlying curves.
   * 
   * @param event  the event
   * @param provider  the rates provider
   * @return the forecast value curve sensitivity of the event
   */
  public abstract PointSensitivityBuilder forecastValueSensitivity(T event, RatesProvider provider);

  //-------------------------------------------------------------------------
  /**
   * Explains the present value of a single payment event.
   * <p>
   * This adds information to the {@link ExplainMapBuilder} to aid understanding of the calculation.
   * 
   * @param event  the event
   * @param provider  the rates provider
   * @param builder  the builder to populate
   */
  public abstract void explainPresentValue(
      T event,
      RatesProvider provider,
      ExplainMapBuilder builder);

  //-------------------------------------------------------------------------
  /**
   * Calculates the currency exposure of a single payment event.
   * 
   * @param event  the event
   * @param provider  the rates provider
   * @return the currency exposure
   */
  public abstract MultiCurrencyAmount currencyExposure(T event, RatesProvider provider);

  /**
   * Calculates the current cash of a single payment event.
   * 
   * @param event  the event
   * @param provider  the rates provider
   * @return the current cash
   */
  public abstract double currentCash(T event, RatesProvider provider);
}
