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

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

#include "base/bind.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
#include "base/task_runner.h"
#include "base/trace_event/trace_event.h"
#include "cobalt/base/polymorphic_downcast.h"
#include "cobalt/script/environment_settings.h"
#include "cobalt/script/global_environment.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/client.h"
#include "cobalt/worker/service_worker_global_scope.h"
#include "cobalt/worker/service_worker_jobs.h"
#include "cobalt/worker/service_worker_object.h"

namespace cobalt {
namespace worker {

namespace {
ServiceWorkerObject* GetAssociatedServiceWorker(
    web::EnvironmentSettings* settings) {
  // Ensure this runs in the right thread to dereferences the WeakPtr.
  DCHECK_EQ(settings->context()->message_loop(), base::MessageLoop::current());
  auto* global_scope = settings->context()->GetWindowOrWorkerGlobalScope();
  DCHECK(global_scope->IsServiceWorker());

  return global_scope->AsServiceWorker()->service_worker_object();
}
}  // namespace

Clients::Clients(script::EnvironmentSettings* settings)
    : settings_(
          base::polymorphic_downcast<web::EnvironmentSettings*>(settings)) {}

script::HandlePromiseWrappable Clients::Get(const std::string& id) {
  TRACE_EVENT0("cobalt::worker", "Clients::Get()");
  DCHECK_EQ(base::MessageLoop::current(), settings_->context()->message_loop());
  // Algorithm for get(id):
  //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#clients-get
  // 1. Let promise be a new promise.
  script::HandlePromiseWrappable promise =
      settings_->context()
          ->global_environment()
          ->script_value_factory()
          ->CreateInterfacePromise<scoped_refptr<Client>>();
  std::unique_ptr<script::ValuePromiseWrappable::Reference> promise_reference(
      new script::ValuePromiseWrappable::Reference(this, promise));

  // 2. Run these substeps in parallel:
  ServiceWorkerJobs* jobs = settings_->context()->service_worker_jobs();
  DCHECK(jobs);
  jobs->message_loop()->task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&ServiceWorkerJobs::ClientsGetSubSteps,
                     base::Unretained(jobs),
                     base::Unretained(settings_->context()),
                     base::Unretained(GetAssociatedServiceWorker(settings_)),
                     std::move(promise_reference), id));

  // 3. Return promise.
  return promise;
}

script::HandlePromiseSequenceWrappable Clients::MatchAll(
    const ClientQueryOptions& options) {
  TRACE_EVENT0("cobalt::worker", "Clients::MatchAll()");
  DCHECK_EQ(base::MessageLoop::current(), settings_->context()->message_loop());
  // Algorithm for matchAll():
  //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#clients-matchall
  // 1. Let promise be a new promise.
  auto promise = settings_->context()
                     ->global_environment()
                     ->script_value_factory()
                     ->CreateBasicPromise<script::SequenceWrappable>();
  std::unique_ptr<script::ValuePromiseSequenceWrappable::Reference>
      promise_reference(
          new script::ValuePromiseSequenceWrappable::Reference(this, promise));
  // 2. Run the following steps in parallel:
  ServiceWorkerJobs* jobs = settings_->context()->service_worker_jobs();
  DCHECK(jobs);
  jobs->message_loop()->task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&ServiceWorkerJobs::ClientsMatchAllSubSteps,
                     base::Unretained(jobs),
                     base::Unretained(settings_->context()),
                     base::Unretained(GetAssociatedServiceWorker(settings_)),
                     std::move(promise_reference),
                     options.include_uncontrolled(), options.type()));
  // 3. Return promise.
  return promise;
}

script::HandlePromiseVoid Clients::Claim() {
  TRACE_EVENT0("cobalt::worker", "Clients::Claim()");
  DCHECK_EQ(base::MessageLoop::current(), settings_->context()->message_loop());
  // Algorithm for claim():
  //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#clients-claim
  // 2. Let promise be a new promise.
  // Note: Done first because it's needed for rejecting in step 1.
  auto promise = settings_->context()
                     ->global_environment()
                     ->script_value_factory()
                     ->CreateBasicPromise<void>();
  std::unique_ptr<script::ValuePromiseVoid::Reference> promise_reference(
      new script::ValuePromiseVoid::Reference(this, promise));

  // 1. If the service worker is not an active worker, return a promise rejected
  // with an "InvalidStateError" DOMException.
  ServiceWorkerObject* service_worker = GetAssociatedServiceWorker(settings_);
  DCHECK(service_worker->containing_service_worker_registration());
  if (service_worker != service_worker->containing_service_worker_registration()
                            ->active_worker()) {
    DCHECK(service_worker->state() != kServiceWorkerStateActivated &&
           service_worker->state() != kServiceWorkerStateActivating);
    // Perform the rest of the steps in a task, because the promise has to be
    // returned before we can safely reject it.
    base::MessageLoop::current()->task_runner()->PostTask(
        FROM_HERE,
        base::BindOnce(
            [](std::unique_ptr<script::ValuePromiseVoid::Reference>
                   promise_reference) {
              promise_reference->value().Reject(
                  new web::DOMException(web::DOMException::kInvalidStateErr));
            },
            std::move(promise_reference)));
    return promise;
  }

  DCHECK(service_worker->state() == kServiceWorkerStateActivated ||
         service_worker->state() == kServiceWorkerStateActivating);

  // 3. Run the following substeps in parallel:
  ServiceWorkerJobs* jobs = settings_->context()->service_worker_jobs();
  DCHECK(jobs);
  jobs->message_loop()->task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&ServiceWorkerJobs::ClaimSubSteps, base::Unretained(jobs),
                     base::Unretained(settings_->context()),
                     base::Unretained(GetAssociatedServiceWorker(settings_)),
                     std::move(promise_reference)));
  // 4. Return promise.
  return promise;
}

}  // namespace worker
}  // namespace cobalt
