// Copyright 2022 The Cobalt Authors. 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/web/cache.h"

#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "base/json/string_escape.h"
#include "base/memory/ref_counted.h"
#include "base/strings/string_util.h"
#include "base/time/time.h"
#include "cobalt/base/source_location.h"
#include "cobalt/cache/cache.h"
#include "cobalt/script/global_environment.h"
#include "cobalt/script/source_code.h"
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/v8c_user_object_holder.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/web/cache_utils.h"
#include "cobalt/web/context.h"
#include "cobalt/web/environment_settings_helper.h"
#include "net/url_request/url_request_context.h"
#include "v8/include/v8.h"

namespace cobalt {
namespace web {

namespace {

const disk_cache::ResourceType kResourceType =
    disk_cache::ResourceType::kCacheApi;

}  // namespace

Cache::Fetcher::Fetcher(network::NetworkModule* network_module, const GURL& url,
                        base::OnceCallback<void(bool)> callback)
    : network_module_(network_module),
      url_(url),
      callback_(std::move(callback)),
      buffer_(new net::GrowableIOBuffer()) {
  network_module_->task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&Cache::Fetcher::Start, base::Unretained(this)));
}

std::vector<uint8_t> Cache::Fetcher::BufferToVector() const {
  auto* buffer_begin = reinterpret_cast<const uint8_t*>(buffer_->data());
  return std::vector<uint8_t>(buffer_begin, buffer_begin + buffer_size_);
}

std::string Cache::Fetcher::BufferToString() const {
  return std::string(buffer_->data(), buffer_size_);
}

void Cache::Fetcher::Start() {
  request_ = network_module_->url_request_context()->CreateRequest(
      url_, net::RequestPriority::DEFAULT_PRIORITY, this);
  request_->Start();
}

void Cache::Fetcher::Notify(bool success) {
  // Need to delete |URLRequest| instance on network thread.
  request_.reset();
  std::move(callback_).Run(success);
}

void Cache::Fetcher::OnDone(bool success) {
  buffer_size_ = buffer_->offset();
  buffer_->set_offset(0);
  network_module_->task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&Cache::Fetcher::Notify, base::Unretained(this), success));
}

void Cache::Fetcher::ReadResponse(net::URLRequest* request) {
  int bytes_read = request->Read(buffer_, buffer_->RemainingCapacity());
  bool read_running_async = bytes_read == net::ERR_IO_PENDING;
  bool response_complete = !read_running_async && bytes_read <= 0;
  // If read is still running, the buffer will be written to and then
  // |OnReadCompleted()| will be called.
  if (read_running_async) {
    return;
  }
  if (response_complete) {
    OnDone(/*success=*/bytes_read == net::OK);
    return;
  }

  // Read completed synchronously. Call |OnReadCompleted()| asynchronously to
  // avoid blocking IO.
  base::SequencedTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::BindOnce(&Cache::Fetcher::OnReadCompleted,
                                base::Unretained(this), request, bytes_read));
}

void Cache::Fetcher::OnResponseStarted(net::URLRequest* request,
                                       int net_error) {
  DCHECK_NE(net::ERR_IO_PENDING, net_error);
  request->GetMimeType(&mime_type_);
  if (net_error != net::OK) {
    OnDone(/*success=*/false);
    return;
  }
  int initial_capacity = request->response_headers()->HasHeader(
                             net::HttpRequestHeaders::kContentLength)
                             ? request->response_headers()->GetContentLength()
                             : 64 * 1024;
  buffer_->SetCapacity(initial_capacity);
  ReadResponse(request);
}

void Cache::Fetcher::OnReadCompleted(net::URLRequest* request, int bytes_read) {
  DCHECK_NE(net::ERR_IO_PENDING, bytes_read);
  if (bytes_read <= 0) {
    OnDone(/*success=*/bytes_read == net::OK);
    return;
  }
  // The offset is how much of the buffer is used.
  buffer_->set_offset(buffer_->offset() + bytes_read);
  // Grow the buffer, if needed.
  if (buffer_->RemainingCapacity() == 0) {
    buffer_->SetCapacity(buffer_->capacity() + 16 * 1024);
  }
  ReadResponse(request);
}

script::HandlePromiseAny Cache::Match(
    script::EnvironmentSettings* environment_settings,
    const script::ValueHandleHolder& request) {
  script::HandlePromiseAny promise =
      get_script_value_factory(environment_settings)
          ->CreateBasicPromise<script::Any>();
  auto promise_reference =
      std::make_unique<script::ValuePromiseAny::Reference>(this, promise);
  auto context = get_context(environment_settings);
  context->message_loop()->task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(
          [](script::EnvironmentSettings* environment_settings, uint32_t key,
             std::unique_ptr<script::ValuePromiseAny::Reference>
                 promise_reference) {
            auto global_environment =
                get_global_environment(environment_settings);
            auto* isolate = global_environment->isolate();
            auto cached =
                cache::Cache::GetInstance()->Retrieve(kResourceType, key);
            if (!cached) {
              promise_reference->value().Resolve(
                  cache_utils::GetUndefined(environment_settings));
              return;
            }
            script::v8c::EntryScope entry_scope(isolate);
            auto response = cache_utils::CreateResponse(environment_settings,
                                                        std::move(cached));
            if (!response) {
              promise_reference->value().Reject();
            } else {
              promise_reference->value().Resolve(script::Any(response.value()));
            }
          },
          environment_settings,
          cache_utils::GetKey(environment_settings, request),
          std::move(promise_reference)));
  return promise;
}

void Cache::PerformAdd(
    script::EnvironmentSettings* environment_settings,
    std::unique_ptr<script::ValueHandleHolder::Reference> request_reference,
    std::unique_ptr<script::ValuePromiseVoid::Reference> promise_reference) {
  auto* global_environment = get_global_environment(environment_settings);
  auto* isolate = global_environment->isolate();
  script::v8c::EntryScope entry_scope(isolate);
  uint32_t key = cache_utils::GetKey(environment_settings,
                                     request_reference->referenced_value());
  if (fetchers_.find(key) != fetchers_.end()) {
    base::AutoLock auto_lock(*(fetchers_[key]->lock()));
    auto* promises = &(fetch_contexts_[key].first);
    promises->push_back(std::move(promise_reference));
    return;
  }
  auto promises =
      std::vector<std::unique_ptr<script::ValuePromiseVoid::Reference>>();
  promises.push_back(std::move(promise_reference));
  fetch_contexts_[key] =
      std::make_pair(std::move(promises), environment_settings);
  auto* context = get_context(environment_settings);
  fetchers_[key] = std::make_unique<Cache::Fetcher>(
      context->network_module(),
      GURL(cache_utils::GetUrl(environment_settings,
                               request_reference->referenced_value())),
      base::BindOnce(&Cache::OnFetchCompleted, base::Unretained(this), key));
}

script::HandlePromiseVoid Cache::Add(
    script::EnvironmentSettings* environment_settings,
    const script::ValueHandleHolder& request) {
  auto request_reference =
      std::make_unique<script::ValueHandleHolder::Reference>(this, request);
  script::HandlePromiseVoid promise =
      get_script_value_factory(environment_settings)
          ->CreateBasicPromise<void>();
  auto promise_reference =
      std::make_unique<script::ValuePromiseVoid::Reference>(this, promise);
  auto context = get_context(environment_settings);
  context->message_loop()->task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&Cache::PerformAdd, base::Unretained(this),
                     environment_settings, std::move(request_reference),
                     std::move(promise_reference)));
  return promise;
}

script::HandlePromiseVoid Cache::Put(
    script::EnvironmentSettings* environment_settings,
    const script::ValueHandleHolder& request,
    const script::ValueHandleHolder& response) {
  auto request_reference =
      std::make_unique<script::ValueHandleHolder::Reference>(this, request);
  auto response_reference =
      std::make_unique<script::ValueHandleHolder::Reference>(this, response);
  script::HandlePromiseVoid promise =
      get_script_value_factory(environment_settings)
          ->CreateBasicPromise<void>();
  auto promise_reference =
      std::make_unique<script::ValuePromiseVoid::Reference>(this, promise);

  auto context = get_context(environment_settings);
  base::SequencedTaskRunnerHandle::Get()->PostTask(
      FROM_HERE,
      base::BindOnce(
          [](script::EnvironmentSettings* environment_settings,
             std::unique_ptr<script::ValueHandleHolder::Reference>
                 request_reference,
             std::unique_ptr<script::ValueHandleHolder::Reference>
                 response_reference,
             std::unique_ptr<script::ValuePromiseVoid::Reference>
                 promise_reference) {

            auto* global_environment =
                get_global_environment(environment_settings);
            auto* isolate = global_environment->isolate();
            script::v8c::EntryScope entry_scope(isolate);
            auto context = global_environment->context();
            auto maybe_body_used = cache_utils::TryGet(
                context, GetV8Value(response_reference->referenced_value()),
                "bodyUsed");
            if (maybe_body_used.IsEmpty() ||
                maybe_body_used.ToLocalChecked().As<v8::Boolean>()->Value()) {
              promise_reference->value().Reject(script::kTypeError);
              return;
            }
            auto maybe_text_function = cache_utils::TryGet(
                context, GetV8Value(response_reference->referenced_value()),
                "text");
            if (maybe_text_function.IsEmpty()) {
              promise_reference->value().Reject();
              return;
            }
            auto text_function = maybe_text_function.ToLocalChecked();
            v8::Local<v8::Value> text_result;
            auto response_context =
                script::GetIsolate(response_reference->referenced_value())
                    ->GetCurrentContext();
            if (text_function.IsEmpty() || !text_function->IsFunction() ||
                !(text_function.As<v8::Function>()
                      ->Call(response_context,
                             GetV8Value(response_reference->referenced_value()),
                             /*argc=*/0,
                             /*argv=*/nullptr)
                      .ToLocal(&text_result))) {
              promise_reference->value().Reject();
              return;
            }
            std::string url = cache_utils::GetUrl(
                environment_settings, request_reference->referenced_value());
            auto data = v8::Object::New(isolate);
            cache_utils::Set(context, data, "environment_settings",
                             v8::External::New(isolate, environment_settings));
            cache_utils::Set(
                context, data, "promise_reference",
                v8::External::New(isolate, promise_reference.release()));
            cache_utils::Set(
                context, data, "request_reference",
                v8::External::New(isolate, request_reference.release()));
            auto then_callback =
                v8::Function::New(
                    context,
                    [](const v8::FunctionCallbackInfo<v8::Value>& info) {
                      auto* isolate = info.GetIsolate();
                      auto context = info.GetIsolate()->GetCurrentContext();
                      auto* environment_settings =
                          static_cast<script::EnvironmentSettings*>(
                              cache_utils::Get(context, info.Data(),
                                               "environment_settings")
                                  .As<v8::External>()
                                  ->Value());
                      std::unique_ptr<script::ValueHandleHolder::Reference>
                      request_reference(
                          static_cast<script::ValueHandleHolder::Reference*>(
                              cache_utils::Get(context, info.Data(),
                                               "request_reference")
                                  .As<v8::External>()
                                  ->Value()));
                      std::unique_ptr<script::ValuePromiseVoid::Reference>
                      promise_reference(
                          static_cast<script::ValuePromiseVoid::Reference*>(
                              cache_utils::Get(context, info.Data(),
                                               "promise_reference")
                                  .As<v8::External>()
                                  ->Value()));
                      uint32_t key = cache_utils::GetKey(
                          environment_settings,
                          request_reference->referenced_value());
                      std::string url = cache_utils::GetUrl(
                          environment_settings,
                          request_reference->referenced_value());
                      std::string body;
                      FromJSValue(info.GetIsolate(), info[0],
                                  script::v8c::kNoConversionFlags, nullptr,
                                  &body);
                      auto* begin =
                          reinterpret_cast<const uint8_t*>(body.data());
                      auto data = std::make_unique<std::vector<uint8_t>>(
                          begin, begin + body.size());
                      cache::Cache::GetInstance()->Store(
                          kResourceType, key, *data, base::Value(url));
                      promise_reference->value().Resolve();
                    },
                    data)
                    .ToLocalChecked();
            if (text_result.As<v8::Promise>()
                    ->Then(context, then_callback)
                    .IsEmpty()) {
              promise_reference->value().Reject();
              return;
            }
            auto catch_callback =
                v8::Function::New(
                    context,
                    [](const v8::FunctionCallbackInfo<v8::Value>& info) {
                      auto* isolate = info.GetIsolate();
                      auto context = info.GetIsolate()->GetCurrentContext();
                      std::unique_ptr<script::ValuePromiseVoid::Reference>
                      promise_reference(
                          static_cast<script::ValuePromiseVoid::Reference*>(
                              cache_utils::Get(context, info.Data(),
                                               "promise_reference")
                                  .As<v8::External>()
                                  ->Value()));
                      promise_reference->value().Reject();
                    },
                    data)
                    .ToLocalChecked();
            if (text_result.As<v8::Promise>()
                    ->Catch(context, catch_callback)
                    .IsEmpty()) {
              promise_reference->value().Reject();
              return;
            }
            // Run |response.text()| promise.
            isolate->PerformMicrotaskCheckpoint();
          },
          environment_settings, std::move(request_reference),
          std::move(response_reference), std::move(promise_reference)));
  return promise;
}

script::HandlePromiseBool Cache::Delete(
    script::EnvironmentSettings* environment_settings,
    const script::ValueHandleHolder& request) {
  script::HandlePromiseBool promise =
      get_script_value_factory(environment_settings)
          ->CreateBasicPromise<bool>();
  auto request_reference =
      std::make_unique<script::ValueHandleHolder::Reference>(this, request);
  auto promise_reference =
      std::make_unique<script::ValuePromiseBool::Reference>(this, promise);
  auto context = get_context(environment_settings);
  context->message_loop()->task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(
          [](script::EnvironmentSettings* environment_settings,
             std::unique_ptr<script::ValueHandleHolder::Reference>
                 request_reference,
             std::unique_ptr<script::ValuePromiseBool::Reference>
                 promise_reference) {
            auto* global_environment =
                get_global_environment(environment_settings);
            auto* isolate = global_environment->isolate();
            script::v8c::EntryScope entry_scope(isolate);
            promise_reference->value().Resolve(
                cache::Cache::GetInstance()->Delete(
                    kResourceType, cache_utils::GetKey(
                                       environment_settings,
                                       request_reference->referenced_value())));
          },
          environment_settings, std::move(request_reference),
          std::move(promise_reference)));
  return promise;
}

script::HandlePromiseAny Cache::Keys(
    script::EnvironmentSettings* environment_settings) {
  script::HandlePromiseAny promise =
      get_script_value_factory(environment_settings)
          ->CreateBasicPromise<script::Any>();
  auto promise_reference =
      std::make_unique<script::ValuePromiseAny::Reference>(this, promise);
  auto context = get_context(environment_settings);
  context->message_loop()->task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(
          [](script::EnvironmentSettings* environment_settings,
             std::unique_ptr<script::ValuePromiseAny::Reference>
                 promise_reference) {
            auto* global_environment =
                get_global_environment(environment_settings);
            auto* isolate = global_environment->isolate();
            script::v8c::EntryScope entry_scope(isolate);
            auto keys =
                cache::Cache::GetInstance()->KeysWithMetadata(kResourceType);
            std::vector<v8::Local<v8::Value>> requests;
            for (uint8_t key :
                 cache::Cache::GetInstance()->KeysWithMetadata(kResourceType)) {
              std::unique_ptr<base::Value> url =
                  cache::Cache::GetInstance()->Metadata(kResourceType, key);
              if (url && url->is_string()) {
                base::Optional<script::Any> request =
                    cache_utils::CreateRequest(environment_settings,
                                               url->GetString());
                if (request) {
                  requests.push_back(GetV8Value(*(request->GetScriptValue())));
                }
              }
            }
            promise_reference->value().Resolve(
                script::Any(new script::v8c::V8cValueHandleHolder(
                    isolate, v8::Array::New(isolate, requests.data(),
                                            requests.size()))));

          },
          environment_settings, std::move(promise_reference)));
  return promise;
}

void Cache::OnFetchCompleted(uint32_t key, bool success) {
  auto* environment_settings = fetch_contexts_[key].second;
  auto* context = get_context(environment_settings);
  context->message_loop()->task_runner()->PostTask(
      FROM_HERE, base::BindOnce(&Cache::OnFetchCompletedMainThread,
                                base::Unretained(this), key, success));
}

void Cache::OnFetchCompletedMainThread(uint32_t key, bool success) {
  auto* fetcher = fetchers_[key].get();
  auto* promises = &(fetch_contexts_[key].first);
  if (!success) {
    {
      base::AutoLock auto_lock(*fetcher->lock());
      while (promises->size() > 0) {
        promises->back()->value().Reject();
        promises->pop_back();
      }
    }
    fetchers_.erase(key);
    fetch_contexts_.erase(key);
    return;
  }
  {
    cache::Cache::GetInstance()->Store(kResourceType, key,
                                       fetcher->BufferToVector(),
                                       base::Value(fetcher->url().spec()));
    if (fetcher->mime_type() == "text/javascript") {
      auto* environment_settings = fetch_contexts_[key].second;
      auto* global_environment = get_global_environment(environment_settings);
      auto* isolate = global_environment->isolate();
      script::v8c::EntryScope entry_scope(isolate);
      global_environment->Compile(script::SourceCode::CreateSourceCode(
          fetcher->BufferToString(), base::SourceLocation(__FILE__, 1, 1)));
    }
    base::AutoLock auto_lock(*fetcher->lock());
    while (promises->size() > 0) {
      promises->back()->value().Resolve();
      promises->pop_back();
    }
  }
  fetchers_.erase(key);
  fetch_contexts_.erase(key);
}

}  // namespace web
}  // namespace cobalt
