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

#include <string>
#include <utility>

#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/optional.h"
#include "base/task_runner.h"
#include "base/trace_event/trace_event.h"
#include "cobalt/dom/dom_settings.h"
#include "cobalt/script/promise.h"
#include "cobalt/script/script_value_factory.h"
#include "cobalt/web/context.h"
#include "cobalt/web/dom_exception.h"
#include "cobalt/web/environment_settings.h"
#include "cobalt/worker/registration_options.h"
#include "cobalt/worker/service_worker_update_via_cache.h"
#include "cobalt/worker/worker_type.h"
#include "url/gurl.h"

namespace cobalt {
namespace worker {

ServiceWorkerContainer::ServiceWorkerContainer(
    script::EnvironmentSettings* settings)
    : web::EventTarget(settings) {}

scoped_refptr<ServiceWorker> ServiceWorkerContainer::controller() {
  // Algorithm for controller:
  //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#navigator-service-worker-controller
  // 1. Let client be this's service worker client.
  web::EnvironmentSettings* client = environment_settings();

  // 2. If client’s active service worker is null, then return null.
  if (!client->context()->active_service_worker()) {
    return scoped_refptr<ServiceWorker>();
  }

  // 3. Return the result of getting the service worker object that represents
  //    client’s active service worker in this's relevant settings object.
  return client->context()->GetServiceWorker(
      client->context()->active_service_worker());
}

script::HandlePromiseWrappable ServiceWorkerContainer::ready() {
  // Algorithm for ready attribute:
  //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#navigator-service-worker-ready
  // 1. If this's ready promise is null, then set this's ready promise to a new
  //    promise.
  if (!promise_reference_) {
    ready_promise_ = environment_settings()
                         ->context()
                         ->global_environment()
                         ->script_value_factory()
                         ->CreateInterfacePromise<
                             scoped_refptr<ServiceWorkerRegistration>>();
    promise_reference_.reset(
        new script::ValuePromiseWrappable::Reference(this, ready_promise_));
  }
  // 2. Let readyPromise be this's ready promise.
  script::HandlePromiseWrappable ready_promise(ready_promise_);
  // 3. If readyPromise is pending, run the following substeps in parallel:
  if (ready_promise->State() == script::PromiseState::kPending) {
    //    3.1. Let client by this's service worker client.
    web::EnvironmentSettings* client = environment_settings();
    worker::ServiceWorkerJobs* jobs = client->context()->service_worker_jobs();
    jobs->message_loop()->task_runner()->PostTask(
        FROM_HERE,
        base::BindOnce(&ServiceWorkerJobs::MaybeResolveReadyPromiseSubSteps,
                       base::Unretained(jobs), client));
  }
  // 4. Return readyPromise.
  return ready_promise;
}

void ServiceWorkerContainer::MaybeResolveReadyPromise(
    ServiceWorkerRegistrationObject* registration) {
  // This implements resolving of the ready promise for the Activate algorithm
  // (steps 7.1-7.3) as well as for the ready attribute (step 3.3).
  //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#activation-algorithm
  //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#navigator-service-worker-ready
  TRACE_EVENT0("cobalt::worker",
               "ServiceWorkerContainer::MaybeResolveReadyPromise()");
  DCHECK_EQ(base::MessageLoop::current(),
            environment_settings()->context()->message_loop());
  if (!registration || !registration->active_worker()) return;
  if (!promise_reference_) return;
  if (ready_promise_->State() != script::PromiseState::kPending) return;

  auto registration_object =
      environment_settings()->context()->LookupServiceWorkerRegistration(
          registration);
  if (registration_object) {
    DCHECK(registration_object->active());
    ready_promise_->Resolve(registration_object);
    promise_reference_.reset();
  }
}

script::HandlePromiseWrappable ServiceWorkerContainer::Register(
    const std::string& url) {
  RegistrationOptions options;
  return ServiceWorkerContainer::Register(url, options);
}

script::HandlePromiseWrappable ServiceWorkerContainer::Register(
    const std::string& url, const RegistrationOptions& options) {
  TRACE_EVENT0("cobalt::worker", "ServiceWorkerContainer::Register()");
  DCHECK_EQ(base::MessageLoop::current(),
            environment_settings()->context()->message_loop());
  // https://www.w3.org/TR/2022/CRD-service-workers-20220712/#navigator-service-worker-register
  // 1. Let p be a promise.
  script::HandlePromiseWrappable promise =
      environment_settings()
          ->context()
          ->global_environment()
          ->script_value_factory()
          ->CreateInterfacePromise<scoped_refptr<ServiceWorkerRegistration>>();
  std::unique_ptr<script::ValuePromiseWrappable::Reference> promise_reference(
      new script::ValuePromiseWrappable::Reference(this, promise));

  // 2. Let client be this's service worker client.
  web::EnvironmentSettings* client = environment_settings();
  // 3. Let scriptURL be the result of parsing scriptURL with this's
  // relevant settings object’s API base URL.
  const GURL& base_url = environment_settings()->base_url();
  GURL script_url = base_url.Resolve(url);
  // 4. Let scopeURL be null.
  base::Optional<GURL> scope_url;
  // 5. If options["scope"] exists, set scopeURL to the result of parsing
  //    options["scope"] with this's relevant settings object’s API base URL.
  if (options.has_scope()) {
    scope_url = base_url.Resolve(options.scope());
  }
  // 6. Invoke Start Register with scopeURL, scriptURL, p, client, client’s
  //    creation URL, options["type"], and options["updateViaCache"].
  base::MessageLoop::current()->task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&ServiceWorkerJobs::StartRegister,
                     base::Unretained(client->context()->service_worker_jobs()),
                     scope_url, script_url, std::move(promise_reference),
                     client, options.type(), options.update_via_cache()));
  // 7. Return p.
  return promise;
}

script::HandlePromiseWrappable ServiceWorkerContainer::GetRegistration(
    const std::string& url) {
  TRACE_EVENT0("cobalt::worker", "ServiceWorkerContainer::GetRegistration()");
  DCHECK_EQ(base::MessageLoop::current(),
            environment_settings()->context()->message_loop());
  // Algorithm for 'ServiceWorkerContainer.getRegistration()':
  //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#navigator-service-worker-getRegistration
  // Let promise be a new promise.
  // Perform the rest of the steps in a task, because the promise has to be
  // returned before we can safely reject or resolve it.
  auto promise =
      base::polymorphic_downcast<web::EnvironmentSettings*>(
          environment_settings())
          ->context()
          ->global_environment()
          ->script_value_factory()
          ->CreateInterfacePromise<scoped_refptr<ServiceWorkerRegistration>>();
  std::unique_ptr<script::ValuePromiseWrappable::Reference> promise_reference(
      new script::ValuePromiseWrappable::Reference(this, promise));
  base::MessageLoop::current()->task_runner()->PostTask(
      FROM_HERE, base::BindOnce(&ServiceWorkerContainer::GetRegistrationTask,
                                base::Unretained(this), url,
                                std::move(promise_reference)));
  // 9. Return promise.
  return promise;
}

void ServiceWorkerContainer::GetRegistrationTask(
    const std::string& url,
    std::unique_ptr<script::ValuePromiseWrappable::Reference>
        promise_reference) {
  TRACE_EVENT0("cobalt::worker",
               "ServiceWorkerContainer::GetRegistrationTask()");
  DCHECK_EQ(base::MessageLoop::current(),
            environment_settings()->context()->message_loop());
  // Algorithm for 'ServiceWorkerContainer.getRegistration()':
  //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#navigator-service-worker-getRegistration
  // 1. Let client be this's service worker client.
  web::EnvironmentSettings* client = environment_settings();

  // 2. Let storage key be the result of running obtain a storage key given
  //    client.
  url::Origin storage_key = client->ObtainStorageKey();

  // 3. Let clientURL be the result of parsing clientURL with this's relevant
  //    settings object’s API base URL.
  // TODO(b/234659851): Investigate whether this behaves as expected for empty
  // url values.
  const GURL& base_url = environment_settings()->base_url();
  GURL client_url = base_url.Resolve(url);

  // 4. If clientURL is failure, return a promise rejected with a TypeError.
  if (client_url.is_empty()) {
    promise_reference->value().Reject(script::kTypeError);
    return;
  }

  // 5. Set clientURL’s fragment to null.
  url::Replacements<char> replacements;
  replacements.ClearRef();
  client_url = client_url.ReplaceComponents(replacements);
  DCHECK(!client_url.has_ref() || client_url.ref().empty());

  // 6. If the origin of clientURL is not client’s origin, return a promise
  //    rejected with a "SecurityError" web::DOMException.
  if (client_url.GetOrigin() != base_url.GetOrigin()) {
    promise_reference->value().Reject(
        new web::DOMException(web::DOMException::kSecurityErr));
    return;
  }

  // 7. Let promise be a new promise.
  // 8. Run the following substeps in parallel:
  worker::ServiceWorkerJobs* jobs = client->context()->service_worker_jobs();
  DCHECK(jobs);
  jobs->message_loop()->task_runner()->PostTask(
      FROM_HERE, base::BindOnce(&ServiceWorkerJobs::GetRegistrationSubSteps,
                                base::Unretained(jobs), storage_key, client_url,
                                client, std::move(promise_reference)));
}

script::HandlePromiseSequenceWrappable
ServiceWorkerContainer::GetRegistrations() {
  auto promise = environment_settings()
                     ->context()
                     ->global_environment()
                     ->script_value_factory()
                     ->CreateBasicPromise<script::SequenceWrappable>();
  std::unique_ptr<script::ValuePromiseSequenceWrappable::Reference>
      promise_reference(
          new script::ValuePromiseSequenceWrappable::Reference(this, promise));
  base::MessageLoop::current()->task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&ServiceWorkerContainer::GetRegistrationsTask,
                     base::Unretained(this), std::move(promise_reference)));
  return promise;
}

void ServiceWorkerContainer::GetRegistrationsTask(
    std::unique_ptr<script::ValuePromiseSequenceWrappable::Reference>
        promise_reference) {
  auto* client = environment_settings();
  // https://w3c.github.io/ServiceWorker/#navigator-service-worker-getRegistrations
  worker::ServiceWorkerJobs* jobs =
      environment_settings()->context()->service_worker_jobs();
  url::Origin storage_key = environment_settings()->ObtainStorageKey();
  jobs->message_loop()->task_runner()->PostTask(
      FROM_HERE, base::BindOnce(&ServiceWorkerJobs::GetRegistrationsSubSteps,
                                base::Unretained(jobs), storage_key, client,
                                std::move(promise_reference)));
}

void ServiceWorkerContainer::StartMessages() {}

}  // namespace worker
}  // namespace cobalt
