// Copyright 2016 Google Inc. All Rights Reserved.
//
// 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.

#include "cobalt/webdriver/protocol/cookie.h"

#include "base/string_split.h"
#include "base/stringprintf.h"

namespace cobalt {
namespace webdriver {
namespace protocol {
namespace {
// The key for the JSON Cookie object in the parameters.
const char kCookieKey[] = "cookie";

// JSON Cookie object keys.
const char kNameKey[] = "name";
const char kValueKey[] = "value";
const char kDomainKey[] = "domain";
const char kPathKey[] = "path";
const char kSecureKey[] = "secure";
const char kHttpOnlyKey[] = "httpOnly";
const char kExpiryKey[] = "expiry";
}  // namespace

scoped_ptr<base::Value> Cookie::ToValue(const Cookie& cookie) {
  scoped_ptr<base::DictionaryValue> cookie_value(new base::DictionaryValue());
  cookie_value->SetString(kNameKey, cookie.name_);
  cookie_value->SetString(kValueKey, cookie.value_);
  return cookie_value.PassAs<base::Value>();
}

base::optional<Cookie> Cookie::FromValue(const base::Value* value) {
  // TODO: Malformed data should return an "unable to set cookie"
  // error, but the current implementation will return "invalid parameter".
  const base::DictionaryValue* dictionary_value;
  if (!value->GetAsDictionary(&dictionary_value)) {
    DLOG(INFO) << "Parameter is not a dictionary.";
    return base::nullopt;
  }

  const base::DictionaryValue* cookie_dictionary_value;
  if (!dictionary_value->GetDictionary(kCookieKey, &cookie_dictionary_value)) {
    DLOG(INFO) << StringPrintf("Value of key [%s] is not a JSON object.",
                               kCookieKey);
    return base::nullopt;
  }

  std::string cookie_name;
  std::string cookie_value;
  // Name and value are required.
  if (!cookie_dictionary_value->GetString(kNameKey, &cookie_name) ||
      !cookie_dictionary_value->GetString(kValueKey, &cookie_value)) {
    DLOG(INFO) << StringPrintf(
        "cookie.%s or cookie.%s either does not exist or is not a string",
        kNameKey, kValueKey);
    return base::nullopt;
  }

  Cookie new_cookie(cookie_name, cookie_value);

  std::string string_value;
  if (cookie_dictionary_value->HasKey(kDomainKey)) {
    if (cookie_dictionary_value->GetString(kDomainKey, &string_value)) {
      new_cookie.domain_ = string_value;
    } else {
      DLOG(INFO) << StringPrintf("cookie.%s is not a string", kDomainKey);
      return base::nullopt;
    }
  }
  if (cookie_dictionary_value->HasKey(kPathKey)) {
    if (cookie_dictionary_value->GetString(kPathKey, &string_value)) {
      new_cookie.path_ = string_value;
    } else {
      DLOG(INFO) << StringPrintf("cookie.%s is not a string", kPathKey);
      return base::nullopt;
    }
  }

  bool bool_value = false;
  if (cookie_dictionary_value->HasKey(kSecureKey)) {
    if (cookie_dictionary_value->GetBoolean(kSecureKey, &bool_value)) {
      new_cookie.secure_ = bool_value;
    } else {
      DLOG(INFO) << StringPrintf("cookie.%s is not a boolean", kSecureKey);
      return base::nullopt;
    }
  }
  if (cookie_dictionary_value->HasKey(kHttpOnlyKey)) {
    if (cookie_dictionary_value->GetBoolean(kHttpOnlyKey, &bool_value)) {
      new_cookie.http_only_ = bool_value;
    } else {
      DLOG(INFO) << StringPrintf("cookie.%s is not a boolean", kHttpOnlyKey);
      return base::nullopt;
    }
  }

  int timestamp_value = 0;
  if (cookie_dictionary_value->HasKey(kExpiryKey)) {
    if (cookie_dictionary_value->GetInteger(kExpiryKey, &timestamp_value)) {
      base::TimeDelta seconds_since_epoch =
          base::TimeDelta::FromSeconds(timestamp_value);
      new_cookie.expiry_time_ = base::Time::UnixEpoch() + seconds_since_epoch;
    } else {
      DLOG(INFO) << StringPrintf("cookie.%s is not an integer", kExpiryKey);
      return base::nullopt;
    }
  }
  return new_cookie;
}

void Cookie::ToCookieVector(const std::string& cookies_string,
                            std::vector<Cookie>* cookies) {
  std::vector<std::string> cookie_strings;
  base::SplitString(cookies_string, ';', &cookie_strings);
  for (size_t i = 0; i < cookie_strings.size(); ++i) {
    base::optional<Cookie> cookie = FromString(cookie_strings[i]);
    if (cookie) {
      cookies->push_back(*cookie);
    }
  }
}

base::optional<Cookie> Cookie::FromString(const std::string& cookie_as_string) {
  size_t pos = cookie_as_string.find('=');
  if (pos == std::string::npos) {
    return base::nullopt;
  }
  DCHECK(pos < cookie_as_string.size());
  return Cookie(cookie_as_string.substr(0, pos),
                cookie_as_string.substr(pos + 1));
}

std::string Cookie::ToCookieString(const std::string& current_domain) const {
  base::Time expiry_time;
  if (expiry_time_) {
    expiry_time = expiry_time_.value();
  } else {
    // If expiry was not set by the client, then the default is 20 years from
    // now.
    base::Time::Exploded exploded_now;
    base::Time::Now().UTCExplode(&exploded_now);
    exploded_now.year += 20;
    expiry_time = base::Time::FromUTCExploded(exploded_now);
  }

  // WebDriver protocol defines expiry as seconds since the Unix Epoch, but
  // the Max-Age attribute defines it as seconds from right now.
  base::TimeDelta max_age = expiry_time - base::Time::Now();

  std::string cookie_string =
      StringPrintf("%s=%s; Path=%s; Domain=%s; Max-Age=%d%s%s", name_.c_str(),
                   value_.c_str(), path_.value_or("/").c_str(),
                   domain_.value_or(current_domain).c_str(),
                   static_cast<int>(max_age.InSeconds()),
                   secure_.value_or(false) ? " ;Secure" : "",
                   http_only_.value_or(false) ? " ;HttpOnly" : "");
  return cookie_string;
}

}  // namespace protocol
}  // namespace webdriver
}  // namespace cobalt
