// Copyright 2014 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <brillo/http/http_utils.h>

#include <algorithm>

#include <base/bind.h>
#include <base/json/json_reader.h>
#include <base/json/json_writer.h>
#include <base/values.h>
#include <brillo/data_encoding.h>
#include <brillo/errors/error_codes.h>
#include <brillo/mime_utils.h>
#include <brillo/streams/memory_stream.h>

using brillo::mime::AppendParameter;
using brillo::mime::RemoveParameters;

namespace brillo {
namespace http {

std::unique_ptr<Response> GetAndBlock(const std::string& url,
                                      const HeaderList& headers,
                                      std::shared_ptr<Transport> transport,
                                      brillo::ErrorPtr* error) {
  return SendRequestWithNoDataAndBlock(
      request_type::kGet, url, headers, transport, error);
}

RequestID Get(const std::string& url,
              const HeaderList& headers,
              std::shared_ptr<Transport> transport,
              const SuccessCallback& success_callback,
              const ErrorCallback& error_callback) {
  return SendRequestWithNoData(request_type::kGet,
                               url,
                               headers,
                               transport,
                               success_callback,
                               error_callback);
}

std::unique_ptr<Response> HeadAndBlock(const std::string& url,
                                       std::shared_ptr<Transport> transport,
                                       brillo::ErrorPtr* error) {
  return SendRequestWithNoDataAndBlock(
      request_type::kHead, url, {}, transport, error);
}

RequestID Head(const std::string& url,
               std::shared_ptr<Transport> transport,
               const SuccessCallback& success_callback,
               const ErrorCallback& error_callback) {
  return SendRequestWithNoData(request_type::kHead,
                               url,
                               {},
                               transport,
                               success_callback,
                               error_callback);
}

std::unique_ptr<Response> PostTextAndBlock(const std::string& url,
                                           const std::string& data,
                                           const std::string& mime_type,
                                           const HeaderList& headers,
                                           std::shared_ptr<Transport> transport,
                                           brillo::ErrorPtr* error) {
  return PostBinaryAndBlock(
      url, data.data(), data.size(), mime_type, headers, transport, error);
}

RequestID PostText(const std::string& url,
                   const std::string& data,
                   const std::string& mime_type,
                   const HeaderList& headers,
                   std::shared_ptr<Transport> transport,
                   const SuccessCallback& success_callback,
                   const ErrorCallback& error_callback) {
  return PostBinary(url,
                    data.data(),
                    data.size(),
                    mime_type,
                    headers,
                    transport,
                    success_callback,
                    error_callback);
}

std::unique_ptr<Response> SendRequestAndBlock(
    const std::string& method,
    const std::string& url,
    const void* data,
    size_t data_size,
    const std::string& mime_type,
    const HeaderList& headers,
    std::shared_ptr<Transport> transport,
    brillo::ErrorPtr* error) {
  Request request(url, method, transport);
  request.AddHeaders(headers);
  if (data_size > 0) {
    CHECK(!mime_type.empty()) << "MIME type must be specified if request body "
                                 "message is provided";
    request.SetContentType(mime_type);
    if (!request.AddRequestBody(data, data_size, error))
      return std::unique_ptr<Response>();
  }
  return request.GetResponseAndBlock(error);
}

std::unique_ptr<Response> SendRequestWithNoDataAndBlock(
    const std::string& method,
    const std::string& url,
    const HeaderList& headers,
    std::shared_ptr<Transport> transport,
    brillo::ErrorPtr* error) {
  return SendRequestAndBlock(
      method, url, nullptr, 0, {}, headers, transport, error);
}

RequestID SendRequest(const std::string& method,
                      const std::string& url,
                      StreamPtr stream,
                      const std::string& mime_type,
                      const HeaderList& headers,
                      std::shared_ptr<Transport> transport,
                      const SuccessCallback& success_callback,
                      const ErrorCallback& error_callback) {
  Request request(url, method, transport);
  request.AddHeaders(headers);
  if (stream && (!stream->CanGetSize() || stream->GetRemainingSize() > 0)) {
    CHECK(!mime_type.empty()) << "MIME type must be specified if request body "
                                 "message is provided";
    request.SetContentType(mime_type);
    brillo::ErrorPtr error;
    if (!request.AddRequestBody(std::move(stream), &error)) {
      transport->RunCallbackAsync(
          FROM_HERE, base::Bind(error_callback,
                                0, base::Owned(error.release())));
      return 0;
    }
  }
  return request.GetResponse(success_callback, error_callback);
}

RequestID SendRequest(const std::string& method,
                      const std::string& url,
                      const void* data,
                      size_t data_size,
                      const std::string& mime_type,
                      const HeaderList& headers,
                      std::shared_ptr<Transport> transport,
                      const SuccessCallback& success_callback,
                      const ErrorCallback& error_callback) {
  return SendRequest(method,
                     url,
                     MemoryStream::OpenCopyOf(data, data_size, nullptr),
                     mime_type,
                     headers,
                     transport,
                     success_callback,
                     error_callback);
}

RequestID SendRequestWithNoData(const std::string& method,
                                const std::string& url,
                                const HeaderList& headers,
                                std::shared_ptr<Transport> transport,
                                const SuccessCallback& success_callback,
                                const ErrorCallback& error_callback) {
  return SendRequest(method,
                     url,
                     {},
                     {},
                     headers,
                     transport,
                     success_callback,
                     error_callback);
}

std::unique_ptr<Response> PostBinaryAndBlock(
    const std::string& url,
    const void* data,
    size_t data_size,
    const std::string& mime_type,
    const HeaderList& headers,
    std::shared_ptr<Transport> transport,
    brillo::ErrorPtr* error) {
  return SendRequestAndBlock(request_type::kPost,
                             url,
                             data,
                             data_size,
                             mime_type,
                             headers,
                             transport,
                             error);
}

RequestID PostBinary(const std::string& url,
                     StreamPtr stream,
                     const std::string& mime_type,
                     const HeaderList& headers,
                     std::shared_ptr<Transport> transport,
                     const SuccessCallback& success_callback,
                     const ErrorCallback& error_callback) {
  return SendRequest(request_type::kPost,
                     url,
                     std::move(stream),
                     mime_type,
                     headers,
                     transport,
                     success_callback,
                     error_callback);
}

RequestID PostBinary(const std::string& url,
                     const void* data,
                     size_t data_size,
                     const std::string& mime_type,
                     const HeaderList& headers,
                     std::shared_ptr<Transport> transport,
                     const SuccessCallback& success_callback,
                     const ErrorCallback& error_callback) {
  return SendRequest(request_type::kPost,
                     url,
                     data,
                     data_size,
                     mime_type,
                     headers,
                     transport,
                     success_callback,
                     error_callback);
}

std::unique_ptr<Response> PostFormDataAndBlock(
    const std::string& url,
    const FormFieldList& data,
    const HeaderList& headers,
    std::shared_ptr<Transport> transport,
    brillo::ErrorPtr* error) {
  std::string encoded_data = brillo::data_encoding::WebParamsEncode(data);
  return PostBinaryAndBlock(url,
                            encoded_data.c_str(),
                            encoded_data.size(),
                            brillo::mime::application::kWwwFormUrlEncoded,
                            headers,
                            transport,
                            error);
}

std::unique_ptr<Response> PostFormDataAndBlock(
    const std::string& url,
    std::unique_ptr<FormData> form_data,
    const HeaderList& headers,
    std::shared_ptr<Transport> transport,
    brillo::ErrorPtr* error) {
  Request request(url, request_type::kPost, transport);
  request.AddHeaders(headers);
  if (!request.AddRequestBodyAsFormData(std::move(form_data), error))
    return std::unique_ptr<Response>();
  return request.GetResponseAndBlock(error);
}

RequestID PostFormData(const std::string& url,
                       const FormFieldList& data,
                       const HeaderList& headers,
                       std::shared_ptr<Transport> transport,
                       const SuccessCallback& success_callback,
                       const ErrorCallback& error_callback) {
  std::string encoded_data = brillo::data_encoding::WebParamsEncode(data);
  return PostBinary(url,
                    encoded_data.c_str(),
                    encoded_data.size(),
                    brillo::mime::application::kWwwFormUrlEncoded,
                    headers,
                    transport,
                    success_callback,
                    error_callback);
}

RequestID PostFormData(const std::string& url,
                       std::unique_ptr<FormData> form_data,
                       const HeaderList& headers,
                       std::shared_ptr<Transport> transport,
                       const SuccessCallback& success_callback,
                       const ErrorCallback& error_callback) {
  Request request(url, request_type::kPost, transport);
  request.AddHeaders(headers);
  brillo::ErrorPtr error;
  if (!request.AddRequestBodyAsFormData(std::move(form_data), &error)) {
    transport->RunCallbackAsync(
        FROM_HERE, base::Bind(error_callback, 0, base::Owned(error.release())));
    return 0;
  }
  return request.GetResponse(success_callback, error_callback);
}

std::unique_ptr<Response> PostJsonAndBlock(const std::string& url,
                                           const base::Value* json,
                                           const HeaderList& headers,
                                           std::shared_ptr<Transport> transport,
                                           brillo::ErrorPtr* error) {
  std::string data;
  if (json)
    base::JSONWriter::Write(*json, &data);
  std::string mime_type = AppendParameter(brillo::mime::application::kJson,
                                          brillo::mime::parameters::kCharset,
                                          "utf-8");
  return PostBinaryAndBlock(
      url, data.c_str(), data.size(), mime_type, headers, transport, error);
}

RequestID PostJson(const std::string& url,
                   std::unique_ptr<base::Value> json,
                   const HeaderList& headers,
                   std::shared_ptr<Transport> transport,
                   const SuccessCallback& success_callback,
                   const ErrorCallback& error_callback) {
  std::string data;
  if (json)
    base::JSONWriter::Write(*json, &data);
  std::string mime_type = AppendParameter(brillo::mime::application::kJson,
                                          brillo::mime::parameters::kCharset,
                                          "utf-8");
  return PostBinary(url,
                    data.c_str(),
                    data.size(),
                    mime_type,
                    headers,
                    transport,
                    success_callback,
                    error_callback);
}

std::unique_ptr<Response> PatchJsonAndBlock(
    const std::string& url,
    const base::Value* json,
    const HeaderList& headers,
    std::shared_ptr<Transport> transport,
    brillo::ErrorPtr* error) {
  std::string data;
  if (json)
    base::JSONWriter::Write(*json, &data);
  std::string mime_type = AppendParameter(brillo::mime::application::kJson,
                                          brillo::mime::parameters::kCharset,
                                          "utf-8");
  return SendRequestAndBlock(request_type::kPatch,
                             url,
                             data.c_str(),
                             data.size(),
                             mime_type,
                             headers,
                             transport,
                             error);
}

RequestID PatchJson(const std::string& url,
                    std::unique_ptr<base::Value> json,
                    const HeaderList& headers,
                    std::shared_ptr<Transport> transport,
                    const SuccessCallback& success_callback,
                    const ErrorCallback& error_callback) {
  std::string data;
  if (json)
    base::JSONWriter::Write(*json, &data);
  std::string mime_type =
      AppendParameter(brillo::mime::application::kJson,
                      brillo::mime::parameters::kCharset, "utf-8");
  return SendRequest(request_type::kPatch, url, data.c_str(), data.size(),
                     mime_type, headers, transport, success_callback,
                     error_callback);
}

std::unique_ptr<base::DictionaryValue> ParseJsonResponse(
    Response* response,
    int* status_code,
    brillo::ErrorPtr* error) {
  std::unique_ptr<base::DictionaryValue> result;
  if (!response)
    return result;

  if (status_code)
    *status_code = response->GetStatusCode();

  // Make sure we have a correct content type. Do not try to parse
  // binary files, or HTML output. Limit to application/json and text/plain.
  auto content_type = RemoveParameters(response->GetContentType());
  if (content_type != brillo::mime::application::kJson &&
      content_type != brillo::mime::text::kPlain) {
    brillo::Error::AddTo(error, FROM_HERE, brillo::errors::json::kDomain,
                         "non_json_content_type",
                         "Unexpected response content type: " + content_type);
    return result;
  }

  std::string json = response->ExtractDataAsString();
  std::string error_message;
  auto value = base::JSONReader::ReadAndReturnError(json, base::JSON_PARSE_RFC,
                                                    nullptr, &error_message);
  if (!value) {
    brillo::Error::AddToPrintf(error, FROM_HERE, brillo::errors::json::kDomain,
                               brillo::errors::json::kParseError,
                               "Error '%s' occurred parsing JSON string '%s'",
                               error_message.c_str(), json.c_str());
    return result;
  }
  result = base::DictionaryValue::From(std::move(value));
  if (!result) {
    brillo::Error::AddToPrintf(error, FROM_HERE, brillo::errors::json::kDomain,
                               brillo::errors::json::kObjectExpected,
                               "Response is not a valid JSON object: '%s'",
                               json.c_str());
  }
  return result;
}

std::string GetCanonicalHeaderName(const std::string& name) {
  std::string canonical_name = name;
  bool word_begin = true;
  for (char& c : canonical_name) {
    if (c == '-') {
      word_begin = true;
    } else {
      if (word_begin) {
        c = toupper(c);
      } else {
        c = tolower(c);
      }
      word_begin = false;
    }
  }
  return canonical_name;
}

}  // namespace http
}  // namespace brillo
