// 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 WTEST_ENVIRONMENT_H_
#define WTEST_ENVIRONMENT_H_

#include <string>
#include <map>
#include <vector>

#include <Wt/WEnvironment>
#include <Wt/WServer>

namespace Wt {

class WebController;
class Configuration;

namespace Test {

/*! \class WTestEnvironment Wt/Test/WTestEnvironment Wt/Test/WTestEnvironment
 *  \brief An environment for testing purposes.
 *
 * This environment is useful for use in unit tests: you may configure its
 * properties and pass it to the constructor of an application.
 *
 * This is useful for (unit) test-cases:
 * \if cpp
 * \code
 * void testX() {
 *   Test::WTestEnvironment environment;
 *   MyApplication app(environment);
 *   ...
 * }
 * \endcode
 * \elseif java
 * \code
 * void testX() {
 *   WTestEnvironment environment(new Configuration());
 *   MyApplication app(environment);
 *   ...
 * }
 * \endcode
 * \endif
 *
 * \sa WEnvironment, WApplication::WApplication(const WEnvironment&)
 */
class WT_API WTestEnvironment : public WEnvironment
{
public:
#ifndef WT_TARGET_JAVA
  /*! \brief Default constructor.
   *
   * Constructs a test environment that resembles FireFox 3.0 with default
   * settings.
   *
   * The <i>applicationPath</i> is the simulated deployment path. The
   * configuration file points to a wt_config.xml configuration file.
   * The <i>type</i> indicates the application type.
   *
   * After construction, but before passing it to the constructor of a
   * WApplication, you can change any of the environment properties using
   * the setter methods.
   */
  WTestEnvironment(const std::string& applicationPath = "/",
		   const std::string& configurationFile = "",
		   EntryPointType type = Application);
#else
  /*! \brief Default constructor.
   *
   * Constructs a test environment that resembles FireFox 3.0 with default
   * settings.
   *
   * After construction, but before passing it to the constructor of a
   * WApplication, you can change any of the environment properties using
   * the setter methods.
   */
  WTestEnvironment(Configuration *configuration,
		   EntryPointType type = Application);
#endif // WT_TARGET_JAVA

  /**! \brief Destructor.
   */
  ~WTestEnvironment();

  /** \brief Sets parameters to the application.
   *
   * The default value is an empty map.
   *
   * \sa getParameterMap()
   */
  void setParameterMap(const Http::ParameterMap& parameters);

  /** \brief Sets HTTP cookies.
   *
   * The default value is an empty map.
   *
   * \sa cookies()
   */
  void setCookies(const CookieMap& cookies);

  /** \brief Sets a HTTP header value.
   *
   * The default value is no headers.
   *
   * \sa headerValue()
   */
  void setHeaderValue(const std::string& value);

  /** \brief Sets whether cookies are supported.
   *
   * The default value is <i>true</i>.
   *
   * \sa supportsCookies()
   */
  void setSupportsCookies(bool enabled);

  /** \brief Sets whether AJAX is supported.
   *
   * The default value is <i>true</i>.
   *
   * \sa ajax()
   */
  void setAjax(bool enabled);

  /** \brief Sets the display's DPI scale.
   *
   * The default value is 1.
   *
   * \sa dpiScale()
   */
  void setDpiScale(double dpiScale);

  /** \brief Sets the locale.
   *
   * The default value is "en".
   *
   * \sa locale()
   */
  void setLocale(const WT_LOCALE& locale);

  /** \brief Sets the host name.
   *
   * The default value is "localhost".
   *
   * \sa hostName()
   */
  void setHostName(const std::string& hostName);

  /** \brief Sets the URL scheme.
   *
   * The default value is "http".
   *
   * \sa urlScheme()
   */
  void setUrlScheme(const std::string& scheme);

  /** \brief Sets the user agent.
   *
   * The default value is no "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.0.11) Gecko/2009060309 Ubuntu/9.04 (jaunty) Firefox/3.0.11".
   *
   * \sa userAgent()
   */
  void setUserAgent(const std::string& userAgent);

  /** \brief Sets the referer.
   *
   * The default value is "".
   *
   * \sa referer()
   */
  void setReferer(const std::string& referer);

  /** \brief Sets the accept header.
   *
   * The default value is
   * "text/html,application/xhtml+xml,application/xml;q=0.9,* /*;q=0.8".
   *
   * \sa accept()
   */
  void setAccept(const std::string& accept);

  /** \brief Sets the server signature.
   *
   * The default value is "None (WTestEnvironment)".
   *
   * \sa serverSignature()
   */
  void setServerSignature(const std::string& signature);

  /** \brief Sets the server software.
   *
   * The default value is "None (WTestEnvironment)".
   *
   * \sa serverSoftware()
   */
  void setServerSoftware(const std::string& software);

  /** \brief Sets the server admin.
   *
   * The default value is "your@onyourown.here".
   *
   * \sa serverAdmin()
   */
  void setServerAdmin(const std::string& serverAdmin);

  /** \brief Sets the client address.
   *
   * The default value is "127.0.0.1".
   *
   * \sa clientAddress()
   */
  void setClientAddress(const std::string& clientAddress);

  /** \brief Sets the initial internal path.
   *
   * The default value is "".
   *
   * \sa internalPath()
   */
  void setInternalPath(const std::string& internalPath);

  /** \brief Sets the content type.
   *
   * The default value is XHTML1.
   *
   * \sa contentType()
   */
  void setContentType(ContentType contentType);

private:
  Configuration *configuration_;
  WebSession    *session;
  WebController *controller_;

  void init(EntryPointType type);
};

}

}

#endif // WTEST_ENVIRONMENT_H_
