/*
 * Copyright 2018 syslandscape <contact@syslandscape.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#pragma once

#include <map>
#include <set>
#include <experimental/optional>
#include <syslandscape/http/Types.hpp>
#include <syslandscape/http/Url.hpp>
#include <syslandscape/http/Cookies.hpp>

namespace syslandscape::http {

class HttpRequest {
public:

  HttpRequest();

  HttpRequest(HttpRequest &&);

  HttpRequest(const HttpRequest &) = delete;

  virtual ~HttpRequest() = default;

  void setUserAgent(const std::string &);

  void prepare();

  Cookies & getCookies();

  const Url & getUrl() const;

  void setProtocol(Protocol);

  Protocol getProtocol() const;

  std::string getUserAgent() const;

  void setPath(const std::string &);

  std::string getPath() const;

  void setContentType(const std::string &);

  std::string getContentType() const;

  bool hasHeader(const std::string &) const;

  std::experimental::optional<std::string> getHeader(const std::string &) const;

  bool getKeepAlive() const;

  HttpVersion getHttpVersion() const;

  bool hasParameter(const std::string &) const;

  std::set<std::string> getParameterNames() const;

  std::string getParameter(const std::string &) const;

  const std::set<std::string> &getParameters(const std::string &) const;

  NativeRequest &native();

private:

  static const std::string DEFAULT_USER_AGENT;

  Protocol protocol;

  NativeRequest request;

  Cookies cookies;

  Url url;

  /**
   * Extra information sent with request - query string or posted
   * form.
   */
  std::map<std::string, std::set<std::string>> parameters;

  void setupCookies();

  /**
   * Reconstructs client's URL, based on "Host" header and request
   * URL.
   *
   * @throws MalformedURLException
   */
  void setupUrl();

  /**
   * Parse query into #parameters.
   */
  void setupQueryParameters();

  /**
   * Method parse request body in case of "Content-Type:
   * application/x-www-form-urlencoded" header.
   *
   * Request body data is not consumed, so it is available for later
   * use if needed.
   */
  void setupUrlEncodedContent();

  /**
   * Parse url encoded parameters and adds them to #_parameters.
   *
   * @param parameters
   */
  void parseUrlEncodedParameters(const std::string &);


};

} // namespace syslandscape::http
