// This may look like C code, but it's really -*- C++ -*-
/*
 * Copyright (C) 2008 Emweb bvba, Kessel-Lo, Belgium.
 *
 * See the LICENSE file for terms of use.
 */

#ifndef WDATE_VALIDATOR_H_
#define WDATE_VALIDATOR_H_

#include <Wt/WDate>
#include <Wt/WValidator>

namespace Wt {

/*! \brief A validator for date strings.
 *
 * This validator accepts input in the given date format, and
 * optionally checks if the date is within a given range.
 *
 * The format string used for validating user input are the same as
 * those used by WDate::fromString(const WString&, const WString&).
 */
class WT_API WDateValidator : public WValidator
{
public:
  /*! \brief Construct a date validator.
   *
   * The validator will accept any date of the format 'yyyy-MM-dd'.
   */
  WDateValidator(WObject *parent = 0);

  /*! \brief Construct a date validator.
   *
   * The validator will accept dates in the indicated range in the
   * format 'yyyy-MM-dd'.
   */
  WDateValidator(const WDate& bottom,
		 const WDate& top, WObject *parent = 0);

  /*! \brief Construct a date validator.
   *
   * The validator will accept dates in the date format <i>format</i>.
   *
   * The syntax for <i>format</i> is as in WDate::fromString(const
   * WString&, const WString&)
   */
  WDateValidator(const WString& format, WObject *parent = 0);

  /*! \brief Construct a date validator.
   *
   * The validator will accept only dates within the indicated range
   * <i>bottom</i> to <i>top</i>, in the date format <i>format</i>.
   *
   * The syntax for <i>format</i> is as in WDate::fromString(const
   * WString&, const WString&)
   */
  WDateValidator(const WString& format,
		 const WDate& bottom,
		 const WDate& top, WObject *parent = 0);

  /*! \brief Set the bottom of the valid date range.
   *
   * The default is a null date constructed using WDate().
   */
  void setBottom(const WDate& bottom);

  /*! \brief Get the bottom date of the valid range.
   */
  const WDate& bottom() const { return bottom_; }

  /*! \brief Set the top of the valid date range.
   *
   * The default is a null date constructed using WDate().
   */
  void setTop(const WDate& top);

  /*! \brief Get the top date of the valid range.
   */
  const WDate& top() const { return top_; }

  /*! \brief Set the date format used to parse date strings.
   *
   * \sa WDate::fromString(const WString&, const WString&)
   */
  void setFormat(const WString& format);

  /*! \brief Get the format string used to parse date strings
   *
   * \sa setFormat()
   */
  const WString& format() const { return format_; }

  /*! \brief Validate the given input.
   *
   * The input is considered valid only when it is blank for a
   * non-mandatory field, or represents a date in the given format,
   * and within the valid range.
   */
  virtual State validate(WString& input, int& pos) const;

  virtual void createExtConfig(std::ostream& config) const;

  /*! \brief Parse a date from a string (<b>deprecated</b>).
   *
   * \deprecated see WDate::fromString() static methods.
   *
   * Equivalent to WDate::fromString(<i>input</i>, "yyyy-MM-dd");
   */
  static WDate parse(const WString& input);

  /*! \brief Set the message to display when the input is not a date.
   *
   * The default message is "The date must be of the format {1}", with
   * as first argument the format string.
   */
  void setInvalidNotADateText(const WString& text);

  /*! \brief Returns the message displayed when the input is not a date.
   *
   * \sa setInvalidNotADateText(const WString&)
   */
  WString invalidNotADateText() const;

  /*! \brief Set message to display when the date is earlier than bottom
   *
   * Depending on whether bottom() and top() are \link WDate::isNull
   * defined\endlink, the default message is "The date must be
   * between {1} and {2}" or "The date must be after {1}".
   */
  void setInvalidTooEarlyText(const WString& text);

  /*! \brief Returns the message displayed when date is too early.
   *
   * \sa setInvalidTooEarlyText(const WString&)
   */
  WString invalidTooEarlyText() const;

  /*! \brief Set message to display when the date is later than top.
   *
   * Depending on whether bottom() and top() are \link WDate::isNull
   * defined\endlink, the default message is "The date must be
   * between {1} and {2}" or "The date must be before {2}".
   */
  void setInvalidTooLateText(const WString& text);

  /*! \brief Returns the message displayed when the date is too late.
   *
   * \sa setInvalidTooLateText(const WString&)
   */
  WString invalidTooLateText() const;

protected:
  std::string javaScriptValidate(const std::string& jsRef) const;

private:
  WString format_;
  WDate   bottom_, top_;

  WString tooEarlyText_;
  WString tooLateText_;
  WString notADateText_;
};

}

#endif // DATE_VALIDATOR_H_
