/**
 *
 *  @file drogon_plugin_SecureSSLRedirector.h
 *
 */

#pragma once
#include <drogon/exports.h>
#include <drogon/drogon_callbacks.h>
#include <drogon/plugins/Plugin.h>
#include <regex>
#include <memory>

namespace drogon
{
namespace plugin
{
/**
 * @brief This plugin is used to redirect all non-HTTPS requests to HTTPS
 * (except for those URLs matching a regular expression listed in
 * the 'ssl_redirect_exempt' list).
 *
 * The json configuration is as follows:
 *
 * @code
   {
      "name": "drogon::plugin::SecureSSLRedirector",
      "dependencies": ["drogon::plugin::Redirector"],
      "config": {
            "ssl_redirect_exempt": ["^/.*\\.jpg", ...],
            "secure_ssl_host": "localhost:8849"
      }
   }
   @endcode
 *
 * ssl_redirect_exempt: must be a string or a string array, present a regular
 expression
 * (for matching the path of a request) or a regular expression list for URLs
 that don't
 * have to be redirected.
 *
 * secure_ssl_host: If this string is not empty, all SSL redirects
 * will be directed to this host rather than the originally-requested host.
 *
 * Enable the plugin by adding the configuration to the list of plugins in the
 * configuration file.
 *
 */
class DROGON_EXPORT SecureSSLRedirector
    : public drogon::Plugin<SecureSSLRedirector>,
      public std::enable_shared_from_this<SecureSSLRedirector>
{
  public:
    SecureSSLRedirector()
    {
    }

    /// This method must be called by drogon to initialize and start the plugin.
    /// It must be implemented by the user.
    void initAndStart(const Json::Value &config) override;

    /// This method must be called by drogon to shutdown the plugin.
    /// It must be implemented by the user.
    void shutdown() override;

  private:
    bool redirectingAdvice(const HttpRequestPtr &,
                           std::string &,
                           std::string &) const;
    bool redirectToSSL(const HttpRequestPtr &,
                       std::string &,
                       std::string &) const;

    std::regex exemptRegex_;
    bool regexFlag_{false};
    std::string secureHost_;
};

}  // namespace plugin
}  // namespace drogon
