// This may look like C code, but it's really -*- C++ -*-
/*
 * Copyright (C) 2012 Emweb bv, Herent, Belgium.
 *
 * See the LICENSE file for terms of use.
 */
#ifndef WT_WTHEME_H
#define WT_WTHEME_H

#include <Wt/WColor.h>
#include <Wt/WObject.h>
#include <Wt/WGlobal.h>
#include <Wt/WValidator.h>

namespace Wt {

class DomElement;
class WStringStream;

/*! \brief Enumeration for the role of a subwidget (for theme support)
 *
 * \sa WTheme::apply()
 */
enum WidgetThemeRole {
  MenuItemIcon = 100,
  MenuItemCheckBox = 101,
  MenuItemClose = 102,

  DialogCoverWidget = 200,
  DialogTitleBar = 201,
  DialogBody = 202,
  DialogFooter = 203,
  DialogCloseIcon = 204,
  DialogContent = 205, // For bootstrap 3 modal-content style

  TableViewRowContainer = 300,

  DatePickerPopup = 400,
  DatePickerIcon = 401,
  TimePickerPopup = 410,
  TimePickerPopupContent = 411,

  PanelTitleBar = 500,
  PanelCollapseButton = 501,
  PanelTitle = 502,
  PanelBody = 503,
  PanelBodyContent = 504,

  AuthWidgets = 600,

  InPlaceEditing = 700,
  InPlaceEditingButtonsContainer = 701,
  InPlaceEditingButton = 702,

  Navbar = 800,
  NavCollapse = 801,
  NavBrand = 802,
  NavbarForm = 803,
  NavbarSearchForm = 804,
  NavbarSearchInput = 805,
  NavbarMenu = 806,
  NavbarBtn = 807,
  NavbarAlignLeft = 808,
  NavbarAlignRight = 809
};

/*! \brief Enumeration for the role of a css class (for theme support)
 *
 * \sa WTheme::utilityCssClass()
 */
enum UtilityCssClassRole {
  ToolTipInner = 100,
  ToolTipOuter = 101
};

/*! \brief Enumeration for the role of a DOM element (for theme support)
 *
 * \sa WTheme::apply()
 */
enum ElementThemeRole {
  MainElement = 0,
  ToggleButtonRole = 1,
  ToggleButtonInput = 2,
  ToggleButtonSpan = 3,

  FormLabel = 4,
  FormText = 5,
  FormButton = 6,
  FileUploadForm = 7,
  FileUploadInput = 8,

  Badge = 9,

  ProgressBarBar = 100,
  ProgressBarLabel = 101
};

/*! \brief Enumeration that indicates what validation styles are to be applie
 *
 * \sa WTheme::applyValidationStyle()
 */
enum class ValidationStyleFlag {
  InvalidStyle = 0x1,
  ValidStyle = 0x2
};

W_DECLARE_OPERATORS_FOR_FLAGS(ValidationStyleFlag)

/** \brief All validation styles */
static const WFlags<ValidationStyleFlag> ValidationAllStyles
  = ValidationStyleFlag::InvalidStyle | ValidationStyleFlag::ValidStyle;

/*! \class WTheme Wt/WTheme.h Wt/WTheme.h
 *
 * Abstract base class for themes in %Wt.
 *
 * \sa WApplication::setTheme()
 */
class WT_API WTheme : public WObject
{
public:
  /*! \brief Constructor.
   */
  WTheme();

  /*! \brief Destructor.
   */
  virtual ~WTheme();

  /*! \brief Returns a theme name.
   *
   * Returns a unique name for the theme. This name is used by the default
   * implementation of resourcesUrl() to compute a location for the theme's
   * resources.
   */
  virtual std::string name() const = 0;

  /*! \brief Returns the URL where theme-related resources are stored.
   *
   * The default implementation considers a folder within %Wt's
   * resource directory, based on the theme name().
   */
  virtual std::string resourcesUrl() const;

  /*! \brief Serves the CSS for the theme.
   *
   * This must serve CSS declarations for the theme.
   *
   * The default implementation serves all the styleSheets().
   */
  virtual void serveCss(WStringStream& out) const;

  /*! \brief Returns a vector with stylesheets for the theme.
   *
   * This should return a vector with stylesheets that implement the
   * theme. This list may be tailored to the current user agent, which
   * is read from the application environment.
   */
  virtual std::vector<WLinkedCssStyleSheet> styleSheets() const = 0;

  /*! \brief Called when the theme is assigned to a WApplication
   *
   * This allows the theme to do things like load resource bundles when it
   * is added to an application using WApplication::setTheme().
   *
   * The default implementation does nothing.
   */
  virtual void init(WApplication *app) const;

  /*! \brief Applies the theme to a child of a composite widget.
   *
   * The \p widgetRole indicates the role that \p child has within the
   * implementation of the \p widget.
   *
   * \sa WWidget::setThemeStyleEnabled()
   */
  virtual void apply(WWidget *widget, WWidget *child, int widgetRole) const;

  /*! \brief Applies the theme to a DOM element that renders a widget.
   *
   * The \p element is a rendered representation of the \p widget, and
   * may be further customized to reflect the theme.
   */
  virtual void apply(WWidget *widget, DomElement& element, int elementRole)
    const = 0;

  /*! \brief Returns a generic CSS class name for a disabled element.
   */
  virtual std::string disabledClass() const = 0;

  /*! \brief Returns a generic CSS class name for an active element.
   */
  virtual std::string activeClass() const = 0;

  /*! \brief Returns a generic CSS class name for the chosen role.
   *
   * \sa WTheme::utilityCssClassRole
   */
  virtual std::string utilityCssClass(int utilityCssClassRole) const = 0;

  /*! \brief Returns whether the theme allows for an anchor to be styled
   *         as a button.
   */
  virtual bool canStyleAnchorAsButton() const = 0;

  /*! \brief Load the required content for validation.
   *
   * The styling, and scripts used for validation are separated. Loading
   * these is not done on theme initialization.
   */
  virtual void loadValidationStyling(WApplication* app) const;

  /*! \brief Applies a style that indicates the result of validation.
   */
  virtual void applyValidationStyle(WWidget *widget,
                    const Wt::WValidator::Result& validation,
                    WFlags<ValidationStyleFlag> flags) const
    = 0;

  virtual bool canBorderBoxElement(const DomElement& element) const = 0;

  /*! \brief Returns which side the WPanel collapse icon should be added on
   *
   * Side is assumed to be Side::Left or Side::Right, other sides are not supported.
   */
  virtual Side panelCollapseIconSide() const;

  /*! \brief Sets the color mode for the theme.
   *
   * The color mode is a string that indicates which color mode the
   * theme be in. The interpretation of the color mode is up to the
   * theme, but it is typically used to indicate a dark or light mode.
   *
   * This is relevant only for themes that support color modes. The
   * default implementation does nothing. You can override this method
   * if you want to support color modes in your theme.
   *
   * \sa WBootstrap5Theme
   */
  virtual void setColorMode(const std::string& mode);

  /*! \brief Returns the current color mode for the theme.
   *
   * The default implementation always returns an empty string.
   *
   * \sa setColorMode()
   */
  virtual std::string colorMode() const;

  /*! \brief Returns the color of the slider ticks.
   *
   * Returns the color that will be used for the ticks of WSliders that
   * do not use native controls.
   *
   * \sa WSlider::setNativeControl()
   */
  virtual WColor sliderTickColor() const { return WColor(0xd7, 0xd7, 0xd7); }

protected:
  /*! \brief Applies the functional part of the theme to a widget's child.
   *
   * Only applies the functional part of the theme. This means that
   * only things that are mandatory for the widget to function properly
   * but depend on the theme are applied.
   *
   * \sa apply(), applyOptionalStyling()
   */
  virtual void applyFunctionalStyling(WWidget *widget, WWidget *child, int widgetRole)
    const = 0;

  /*! \brief Applies the optional part of the theme to a widget's child.
   *
   * Only applies the optional part of the theme. This means that
   * only things that are purely cosmetic and do not affect the
   * functionality of the widget are applied.
   *
   * This should only be called for widgets that have theme styling
   * enabled.
   *
   * \sa apply(),
   *     applyFunctionalStyling(),
   *     WWidget::setThemeStyleEnabled()
   */
  virtual void applyOptionalStyling(WWidget *widget, WWidget *child, int widgetRole)
    const = 0;

  friend class WBootstrapTheme;
};

}

#endif // WT_WTHEME_H
