// 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/worker/fetch_event.h"

#include <memory>
#include <utility>

#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/web/cache_utils.h"
#include "cobalt/web/environment_settings_helper.h"

namespace cobalt {
namespace worker {

FetchEvent::FetchEvent(script::EnvironmentSettings* environment_settings,
                       const std::string& type,
                       const FetchEventInit& event_init_dict)
    : FetchEvent(environment_settings, base::Token(type), event_init_dict,
                 base::MessageLoop::current()->task_runner(),
                 RespondWithCallback(), ReportLoadTimingInfo()) {}

FetchEvent::FetchEvent(
    script::EnvironmentSettings* environment_settings, base::Token type,
    const FetchEventInit& event_init_dict,
    scoped_refptr<base::SingleThreadTaskRunner> callback_task_runner,
    RespondWithCallback respond_with_callback,
    ReportLoadTimingInfo report_load_timing_info)
    : ExtendableEvent(environment_settings, type, event_init_dict),
      environment_settings_(environment_settings),
      callback_task_runner_(callback_task_runner),
      respond_with_callback_(std::move(respond_with_callback)),
      report_load_timing_info_(std::move(report_load_timing_info)) {
  auto script_value_factory =
      web::get_script_value_factory(environment_settings_);
  handled_property_ = std::make_unique<script::ValuePromiseVoid::Reference>(
      this, script_value_factory->CreateBasicPromise<void>());
  request_ = std::make_unique<script::ValueHandleHolder::Reference>(
      this, event_init_dict.request());
  respond_with_done_ = std::make_unique<script::ValuePromiseVoid::Reference>(
      this, script_value_factory->CreateBasicPromise<void>());

  load_timing_info_.request_start = base::TimeTicks::Now();
  load_timing_info_.request_start_time = base::Time::Now();
  load_timing_info_.send_start = base::TimeTicks::Now();
  load_timing_info_.send_end = base::TimeTicks::Now();
  load_timing_info_.service_worker_start_time = base::TimeTicks::Now();
}

base::Optional<v8::Local<v8::Promise>> FetchEvent::GetText(
    v8::Local<v8::Promise> response_promise) {
  callback_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(
                     [](ReportLoadTimingInfo report_load_timing_info,
                        const net::LoadTimingInfo& load_timing_info) {
                       std::move(report_load_timing_info).Run(load_timing_info);
                     },
                     std::move(report_load_timing_info_), load_timing_info_));
  handled_property_->value().Resolve();
  return web::cache_utils::OptionalPromise(
      web::cache_utils::Call(response_promise->Result(), "text"));
}

void FetchEvent::RespondWithDone() { respond_with_done_->value().Resolve(); }

base::Optional<v8::Local<v8::Promise>> FetchEvent::DoRespondWith(
    v8::Local<v8::Promise> text_promise) {
  auto* isolate = text_promise->GetIsolate();
  auto context = isolate->GetCurrentContext();
  auto body = web::cache_utils::FromV8String(text_promise->GetIsolate(),
                                             text_promise->Result());
  auto callback =
      base::BindOnce(&FetchEvent::RespondWithDone, base::Unretained(this));
  web::get_context(environment_settings_)
      ->network_module()
      ->task_runner()
      ->PostTask(
          FROM_HERE,
          base::BindOnce(
              [](scoped_refptr<base::SingleThreadTaskRunner>
                     callback_task_runner,
                 RespondWithCallback respond_with_callback, std::string body,
                 base::MessageLoop* loop, base::OnceClosure callback) {
                callback_task_runner->PostTask(
                    FROM_HERE,
                    base::BindOnce(
                        [](RespondWithCallback respond_with_callback,
                           std::string body) {
                          std::move(respond_with_callback)
                              .Run(std::make_unique<std::string>(
                                  std::move(body)));
                        },
                        std::move(respond_with_callback), std::move(body)));
                loop->task_runner()->PostTask(FROM_HERE, std::move(callback));
              },
              callback_task_runner_, std::move(respond_with_callback_),
              std::move(body), base::MessageLoop::current(),
              std::move(callback)));
  return respond_with_done_->value().promise();
}

void FetchEvent::RespondWith(
    std::unique_ptr<script::Promise<script::ValueHandle*>>& response,
    script::ExceptionState* exception_state) {
  respond_with_called_ = true;

  auto text_promise = web::cache_utils::Then(
      response->promise(),
      base::BindOnce(&FetchEvent::GetText, base::Unretained(this)));
  if (!text_promise) {
    return;
  }
  auto done_promise = web::cache_utils::Then(
      text_promise.value(),
      base::BindOnce(&FetchEvent::DoRespondWith, base::Unretained(this)));
  if (!done_promise) {
    return;
  }
  auto* isolate = response->promise()->GetIsolate();
  std::unique_ptr<script::Promise<script::ValueHandle*>> wait_promise;
  script::v8c::FromJSValue(isolate, done_promise.value(), 0, exception_state,
                           &wait_promise);
  WaitUntil(environment_settings_, response, exception_state);
  WaitUntil(environment_settings_, wait_promise, exception_state);
}

script::HandlePromiseVoid FetchEvent::handled() {
  return script::HandlePromiseVoid(handled_property_->referenced_value());
}

}  // namespace worker
}  // namespace cobalt
