#include "StringUtils.h"

#include <VWeb.h>

namespace VWeb {
void Cookies::Remove(const std::string &name) {
  if (Data.contains(name))
    Data.erase(name);
}
bool Cookies::Has(const std::string &name) const { return Data.contains(name); }
std::string Cookies::TransformToHeader() {
  std::stringstream view{};
  for (auto &cookie : Data) {
    auto &realCookie = cookie.second;
    if (!realCookie.IsOld && !realCookie.Name.empty() &&
        !realCookie.Value.empty())
      CookieToString(view, realCookie);
  }
  return view.str();
}

void Cookies::CreateCookieFromString(const std::string &data) {
  auto params = String::Split(data, ";");
  Cookie cookie{};
  int i = 0;
  for (auto &param : params) {
    auto split = String::Split(param, "=");
    if (split.size() == 1) {
      // we have a bool parameter
      if (split[0] == "HttpOnly")
        cookie.HttpOnly = true;
      else if (split[0] == "Secure")
        cookie.Secure = true;
    } else {
      if (i == 0) {
        cookie.Name = split[0];
        cookie.Value = split[1];
      } else {
        if (split[0] == "SameSite") {
          if (split[1] == "None")
            cookie.SameSite = CookieSameSite::None;
          else if (split[1] == "Lax")
            cookie.SameSite = CookieSameSite::Lax;
          else if (split[1] == "Strict")
            cookie.SameSite = CookieSameSite::Strict;
        } else if (split[0] == "Path")
          cookie.Path = split[1];
        else if (split[0] == "Domain")
          cookie.Domain = split[1];
        else if (split[0] == "Max-Age")
          cookie.MaxAge = String::ToNumber(split[1], 0);
        else if (split[0] == "Expires")
          cookie.Expires = split[1];
      }
    }
    i++;
  }
  if (!cookie.Name.empty() && !cookie.Value.empty())
    Data[cookie.Name] = std::move(cookie);
}

void Cookies::CreateOld(const std::string &name, const std::string &value) {
  auto& cookie = Data[name];
  cookie.Name = name;
  cookie.Value = value;
  cookie.IsOld = true;
}

void Cookies::CookieToString(std::stringstream &stream, Cookie &cookie) {
  if (cookie.Name.empty() || cookie.Value.empty())
    return;
  std::stringstream view{};
  // Cookie names that are starting with __Secure or __Host are Secure only
  // Cookies!
  if (cookie.Name.starts_with("__Secure"))
    cookie.Secure = true;
  if (cookie.Name.starts_with("__Host")) {
    cookie.Secure = true;
    if (cookie.Path.empty())
      cookie.Path = "/";
  }
  view << "Set-Cookie: " << cookie.Name << "=" << cookie.Value;
  if (!cookie.Expires.empty())
    view << "; Expires=" << cookie.Expires;
  if (cookie.MaxAge)
    view << "; Max-Age=" << cookie.MaxAge;
  if (!cookie.Domain.empty())
    view << "; Domain=" << cookie.Domain;
  if (!cookie.Path.empty())
    view << "; Path=" << cookie.Path;
  if (cookie.Secure || cookie.SameSite == CookieSameSite::None)
    view << "; Secure";
  if (cookie.HttpOnly)
    view << "; HttpOnly";
  if (cookie.SameSite != CookieSameSite::Invalid) {
    std::string sameSiteValue;
    switch (cookie.SameSite) {
    case CookieSameSite::None: sameSiteValue = "None"; break;
    case CookieSameSite::Strict: sameSiteValue = "Strict"; break;
    case CookieSameSite::Lax: sameSiteValue = "Lax"; break;
    default: break;
    }
    view << "; SameSite=" << sameSiteValue;
  }
  view << "\n";
}
} // namespace VWeb