#ifndef STAN_MATH_PRIM_SCAL_ERR_OUT_OF_RANGE_HPP
#define STAN_MATH_PRIM_SCAL_ERR_OUT_OF_RANGE_HPP

#include <stan/math/prim/scal/meta/error_index.hpp>
#include <typeinfo>
#include <string>
#include <sstream>
#include <stdexcept>

namespace stan {
  namespace math {

    /**
     * Throw an out_of_range exception with a consistently formatted message.
     *
     * This is an abstraction for all Stan functions to use when throwing
     * out of range. This will allow us to change the behavior for all
     * functions at once.
     *
     * The message is:
     * "<function>: index <index> out of range; expecting index to be between "
     * "1 and <max><msg1><msg2>"
     *
     * @param function Name of the function
     * @param max Max
     * @param index Index
     * @param msg1 Message to print. Default is "".
     * @param msg2 Message to print. Default is "".
     * @throw std::out_of_range with message.
     */
    inline void out_of_range(const std::string& function,
                             int max,
                             int index,
                             const std::string& msg1 = "",
                             const std::string& msg2 = "") {
      std::ostringstream message;

      message << function << ": accessing element out of range. "
              << "index " << index << " out of range; "
              << "expecting index to be between "
              << stan::error_index::value << " and "
              << stan::error_index::value - 1 + max
              << msg1
              << msg2;

      throw std::out_of_range(message.str());
    }

  }
}
#endif
