// Copyright 2010-2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "net/http_client_pepper.h"

#include <ppapi/cpp/instance.h>
#include <ppapi/cpp/url_loader.h>
#include <ppapi/cpp/url_request_info.h>
#include <ppapi/cpp/url_response_info.h>
#include <ppapi/cpp/var.h>
#include <ppapi/utility/completion_callback_factory.h>

#include <memory>

#include "base/logging.h"
#include "base/mutex.h"
#include "base/number_util.h"
#include "base/pepper_scoped_obj.h"
#include "base/util.h"

using std::unique_ptr;

namespace mozc {
namespace {

const int kReadBufferSize = 1024 * 1024;
pp::Instance *g_pepper_instance = NULL;

class PepperURLLoader {
 public:
  PepperURLLoader(HTTPMethodType type,
                  const string &url,
                  const char *post_data,
                  size_t post_size,
                  const HTTPClient::Option &option);
  ~PepperURLLoader();
  bool Start(int32 timeout_millisec, string *output_string);

 private:
  void StartImpl(int32_t result);
  void OnOpen(int32 result);
  void OnRead(int32 result);
  void ReadBody();
  bool AppendDataBytes(const char *buffer, int32 num_bytes);
  bool CheckTimeouted();
  void Complete(bool result);

  const HTTPMethodType type_;
  const string url_;
  string post_data_;
  const HTTPClient::Option option_;
  bool result_;
  bool finished_;
  bool timeouted_;
  unique_ptr<char[]> tmp_buffer_;
  pp::CompletionCallbackFactory<PepperURLLoader> cc_factory_;
  scoped_main_thread_destructed_object<pp::URLRequestInfo> url_request_;
  scoped_main_thread_destructed_object<pp::URLLoader> url_loader_;

  UnnamedEvent event_;
  Mutex mutex_;
  string data_buffer_;

  // The size of response header.
  // It is set when option.include_header is true or HTTPMethodType is HEAD.
  size_t response_header_size_;
  // Content-Length of the response.
  size_t response_content_length_;
};

PepperURLLoader::PepperURLLoader(HTTPMethodType type,
                                 const string &url,
                                 const char *post_data,
                                 size_t post_size,
                                 const HTTPClient::Option &option)
    : type_(type),
      url_(url),
      option_(option),
      result_(false),
      finished_(false),
      timeouted_(false),
      tmp_buffer_(new char[kReadBufferSize]),
      response_header_size_(0),
      response_content_length_(0) {
  if (post_data) {
    post_data_ = string(post_data, post_size);
  }
  cc_factory_.Initialize(this);
}

PepperURLLoader::~PepperURLLoader() {
  VLOG(2) << "PepperURLLoader deleted";
}

void PepperURLLoader::StartImpl(int32_t result) {
  VLOG(2) << "PepperURLLoader::StartImpl";
  if (CheckTimeouted()) {
    VLOG(2) << "PepperURLLoader::StartImpl Timeouted!";
    delete this;
    return;
  }
  CHECK(!url_request_.get());
  CHECK(!url_loader_.get());
  url_request_.reset(new pp::URLRequestInfo(g_pepper_instance));
  url_loader_.reset(new pp::URLLoader(g_pepper_instance));
  url_request_->SetAllowCrossOriginRequests(true);
  url_request_->SetURL(url_);
  switch (type_) {
    case HTTP_GET:
      url_request_->SetMethod("GET");
      break;
    case HTTP_HEAD:
      url_request_->SetMethod("HEAD");
      break;
    case HTTP_POST:
      url_request_->SetMethod("POST");
      break;
  }
  if (!option_.headers.empty()) {
    string headers;
    for (size_t i = 0; i < option_.headers.size(); ++i) {
      const string &header = option_.headers[i];
      if (Util::StartsWith(header, "User-Agent: ")) {
        LOG(ERROR) << "We can't set the custom user agent in Chrome.";
      } else {
        if (!headers.empty()) {
          headers += "\n";
        }
        headers += header;
      }
    }
    url_request_->SetHeaders(headers);
  }

  if (!post_data_.empty()) {
    url_request_->AppendDataToBody(post_data_.data(), post_data_.size());
  }

  url_request_->SetRecordDownloadProgress(true);
  VLOG(2) << "PepperURLLoader::StartImpl url_loader_->Open";
  const int32_t ret = url_loader_->Open(
      *url_request_,
      cc_factory_.NewCallback(&PepperURLLoader::OnOpen));
  if ((ret != PP_OK_COMPLETIONPENDING) && (ret != PP_OK)) {
    VLOG(2) << "url_loader_->Open error. ret: " << ret;
    Complete(false);
    return;
  }
}

void PepperURLLoader::OnOpen(int32 result) {
  VLOG(2) << "PepperURLLoader::OnOpen " << result;
  if (CheckTimeouted()) {
    VLOG(2) << "PepperURLLoader::OnOpen Timeouted!" << result;
    delete this;
    return;
  }
  if (result != PP_OK) {
    VLOG(2) << "pp::URLLoader::Open() failed: " << url_;
    Complete(false);
    return;
  }
  const pp::URLResponseInfo response = url_loader_->GetResponseInfo();
  if (response.GetStatusCode() != 200) {
    VLOG(2) << "pp::URLLoader::Open() failed: " << url_
            << " Status code: " << response.GetStatusCode();
    Complete(false);
    return;
  }

  if (option_.include_header || type_ == HTTP_HEAD) {
    string headers;
    string status_code = NumberUtil::SimpleItoa(response.GetStatusCode());
    string status_line = "OK";

    const pp::Var status_line_var = response.GetStatusLine();
    if (status_line_var.is_string()) {
      status_line = status_line_var.AsString();
    } else {
      LOG(ERROR) << "GetStatusLine Error";
    }
    headers = "HTTP/1.0 " + status_code + " " + status_line + "\n";
    const pp::Var headers_var = response.GetHeaders();
    if (headers_var.is_string()) {
      headers += headers_var.AsString() + "\n";
    }
    headers += "\n";
    response_header_size_ = headers.size();
    data_buffer_ = headers;
    if (response_header_size_ > option_.max_data_size) {
      VLOG(2) << "header_size(" << response_header_size_ <<") is bigger "
              << "than max_data_size(" << option_.max_data_size << ")";
      Complete(false);
      return;
    }
  }

  int64_t bytes_received = 0;
  int64_t bytes_total = 0;
  if (url_loader_->GetDownloadProgress(&bytes_received, &bytes_total)) {
    VLOG(2) << "pp::GetDownloadProgress: bytes_total " << bytes_total;
    if (bytes_total > 0) {
      response_content_length_ = bytes_total;
      const size_t expected_size = response_header_size_ +
                                   response_content_length_;
      if (expected_size > option_.max_data_size) {
        VLOG(2) << "expected_size(" << expected_size << ") is bigger than "
                << "max_data_size(" << option_.max_data_size << ")";
        Complete(false);
        return;
      }
      data_buffer_.reserve(expected_size);
    }
  }
  url_request_->SetRecordDownloadProgress(false);
  ReadBody();
}

bool PepperURLLoader::AppendDataBytes(const char *buffer, int32 num_bytes) {
  if (num_bytes <= 0) {
    return true;
  }
  num_bytes = min(kReadBufferSize, num_bytes);
  if (data_buffer_.size() + num_bytes > option_.max_data_size) {
    VLOG(2) << "PepperURLLoader::AppendDataBytes over flow :"
            << " option_.max_data_size: " << (option_.max_data_size)
            << " data_buffer_.size() + num_bytes: "
            << data_buffer_.size() + num_bytes;
    Complete(false);
    return false;
  }
  data_buffer_.append(buffer, num_bytes);
  return true;
}

void PepperURLLoader::OnRead(int32 result) {
  if (CheckTimeouted()) {
    VLOG(2) << "PepperURLLoader::OnRead Timeouted!";
    delete this;
    return;
  }
  if (result == PP_OK) {
    VLOG(2) << "PepperURLLoader::OnRead Complete!!" << data_buffer_.size();
    if (response_content_length_ != 0) {
      if (data_buffer_.size() !=
              response_content_length_ + response_header_size_) {
        VLOG(2) << "size miss match! actual size:"  << data_buffer_.size()
                << " expected size: "
                << (response_content_length_ - response_header_size_);
        Complete(false);
        return;
      }
    }
    Complete(true);
  } else if (result > 0) {
    if (!AppendDataBytes(tmp_buffer_.get(), result)) {
      return;
    }
    ReadBody();
  } else {
    VLOG(2) << "PepperURLLoader::OnRead ERROR!" << url_;
    Complete(false);
  }
}

void PepperURLLoader::ReadBody() {
  pp::CompletionCallback completion_callback =
      cc_factory_.NewOptionalCallback(&PepperURLLoader::OnRead);
  int32 result = PP_OK;
  do {
    result = url_loader_->ReadResponseBody(tmp_buffer_.get(),
                                           kReadBufferSize,
                                           completion_callback);
    if (result > 0) {
      if (!AppendDataBytes(tmp_buffer_.get(), result)) {
        return;
      }
    }
  } while (result > 0);

  if (result != PP_OK_COMPLETIONPENDING) {
    completion_callback.Run(result);
  }
}

bool PepperURLLoader::Start(int32 timeout_millisec, string *output_string) {
  pp::Module::Get()->core()->CallOnMainThread(
      0,
      cc_factory_.NewCallback(&PepperURLLoader::StartImpl));
  event_.Wait(timeout_millisec);
  VLOG(2) << "PepperURLLoader::GetResult Wait Done";
  bool deletable = false;
  bool result = false;
  {
    scoped_lock l(&mutex_);
    if (finished_) {
      VLOG(2) << "PepperURLLoader::GetResult finished";
      output_string->swap(data_buffer_);
      result = result_;
      deletable = true;
    } else {
      VLOG(2) << "PepperURLLoader::GetResult timeout";
      // PepperURLLoader will be deleted by itself.
      timeouted_ = true;
    }
  }
  if (deletable) {
    delete this;
  }
  return result;
}

bool PepperURLLoader::CheckTimeouted() {
  scoped_lock l(&mutex_);
  return timeouted_;
}

void PepperURLLoader::Complete(bool result) {
  VLOG(2) << "PepperURLLoader::Complete: " << result;
  bool deletable = false;
  {
    scoped_lock l(&mutex_);
    result_ = result;
    if (timeouted_) {
      VLOG(2) << "PepperURLLoader::Complete timeouted";
      deletable = true;
    } else {
      finished_ = true;
      VLOG(2) << "PepperURLLoader::Complete finished";
      event_.Notify();
    }
  }
  if (deletable) {
    delete this;
  }
}

}  // namespace

bool PepperHTTPRequestHandler::Request(HTTPMethodType type,
                                       const string &url,
                                       const char *post_data,
                                       size_t post_size,
                                       const HTTPClient::Option &option,
                                       string *output_string) {
  CHECK(!pp::Module::Get()->core()->IsMainThread());
  CHECK(g_pepper_instance);
  // loader will be deleted by itself.
  PepperURLLoader *loader = new PepperURLLoader(type,
                                                url,
                                                post_data,
                                                post_size,
                                                option);
  return loader->Start(option.timeout, output_string);
}

void RegisterPepperInstanceForHTTPClient(pp::Instance *instance) {
  g_pepper_instance = instance;
}

pp::Instance *GetPepperInstanceForHTTPClient() {
  return g_pepper_instance;
}

}  // namespace mozc
