// 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://w3c.github.io/ServiceWorker/#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_),
                     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://w3c.github.io/ServiceWorker/#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_),
                     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://w3c.github.io/ServiceWorker/#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_),
                     base::Unretained(GetAssociatedServiceWorker(settings_)),
                     std::move(promise_reference)));
  // 4. Return promise.
  return promise;
}

}  // namespace worker
}  // namespace cobalt
