// 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.

#ifndef COBALT_WORKER_SERVICE_WORKER_JOBS_H_
#define COBALT_WORKER_SERVICE_WORKER_JOBS_H_

#include <deque>
#include <map>
#include <memory>
#include <string>
#include <utility>

#include "base/memory/scoped_refptr.h"
#include "base/message_loop/message_loop.h"
#include "base/optional.h"
#include "base/synchronization/lock.h"
#include "base/task/sequence_manager/moveable_auto_lock.h"
#include "cobalt/loader/fetcher_factory.h"
#include "cobalt/loader/script_loader_factory.h"
#include "cobalt/network/network_module.h"
#include "cobalt/script/exception_message.h"
#include "cobalt/script/promise.h"
#include "cobalt/script/script_value.h"
#include "cobalt/script/script_value_factory.h"
#include "cobalt/web/context.h"
#include "cobalt/web/dom_exception.h"
#include "cobalt/worker/service_worker_object.h"
#include "cobalt/worker/service_worker_registration_object.h"
#include "cobalt/worker/service_worker_update_via_cache.h"
#include "starboard/common/atomic.h"
#include "url/gurl.h"
#include "url/origin.h"

namespace cobalt {
namespace worker {

class ServiceWorkerContext;

// Algorithms for Service Worker Jobs.
//   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#algorithms
class ServiceWorkerJobs {
 public:
  // https://www.w3.org/TR/2022/CRD-service-workers-20220712/#dfn-job-type
  enum JobType { kRegister, kUpdate, kUnregister };

  class JobQueue;

  // This type handles the different promise variants used in jobs.
  class JobPromiseType {
   public:
    // Constructors for each promise variant that can be held.
    explicit JobPromiseType(
        std::unique_ptr<script::ValuePromiseBool::Reference> promise_reference);
    explicit JobPromiseType(
        std::unique_ptr<script::ValuePromiseWrappable::Reference>
            promise_reference);

    template <typename PromiseReference>
    static std::unique_ptr<JobPromiseType> Create(
        PromiseReference promise_reference) {
      return std::unique_ptr<JobPromiseType>(
          new JobPromiseType(std::move(promise_reference)));
    }

    void Resolve(const bool result);
    void Resolve(const scoped_refptr<cobalt::script::Wrappable>& result);
    void Reject(script::SimpleExceptionType exception);
    void Reject(web::DOMException::ExceptionCode code,
                const std::string& message);
    void Reject(const scoped_refptr<script::ScriptException>& result);

    bool is_pending() const { return is_pending_.load(); }

   private:
    starboard::atomic_bool is_pending_{true};
    std::unique_ptr<script::ValuePromiseBool::Reference>
        promise_bool_reference_;
    std::unique_ptr<script::ValuePromiseWrappable::Reference>
        promise_wrappable_reference_;
  };

  // https://www.w3.org/TR/2022/CRD-service-workers-20220712/#dfn-job
  struct Job {
    Job(JobType type, const url::Origin& storage_key, const GURL& scope_url,
        const GURL& script_url, web::Context* client,
        std::unique_ptr<JobPromiseType> promise)
        : type(type),
          storage_key(storage_key),
          scope_url(scope_url),
          script_url(script_url),
          update_via_cache(
              ServiceWorkerUpdateViaCache::kServiceWorkerUpdateViaCacheImports),
          client(client),
          promise(std::move(promise)) {}
    ~Job() {
      client = nullptr;
      containing_job_queue = nullptr;
    }

    // Job properties from the spec.
    //
    JobType type;
    url::Origin storage_key;
    GURL scope_url;
    GURL script_url;
    ServiceWorkerUpdateViaCache update_via_cache;
    web::Context* client;
    GURL referrer;
    std::unique_ptr<JobPromiseType> promise;
    JobQueue* containing_job_queue = nullptr;
    std::deque<std::unique_ptr<Job>> equivalent_jobs;
    bool force_bypass_cache_flag = false;
    bool no_promise_okay = false;

    // Custom, not in the spec.
    //

    // This lock is for the list of equivalent jobs. It should also be held when
    // resolving the promise.
    base::Lock equivalent_jobs_promise_mutex;

    // The loader that is used for asynchronous loads.
    std::unique_ptr<loader::Loader> loader;
  };

  // https://www.w3.org/TR/2022/CRD-service-workers-20220712/#dfn-job-queue
  class JobQueue {
   public:
    bool empty() {
      base::AutoLock lock(mutex_);
      return jobs_.empty();
    }
    void Enqueue(std::unique_ptr<Job> job) {
      base::AutoLock lock(mutex_);
      jobs_.push_back(std::move(job));
    }
    std::unique_ptr<Job> Dequeue() {
      base::AutoLock lock(mutex_);
      std::unique_ptr<Job> job;
      job.swap(jobs_.front());
      jobs_.pop_front();
      return job;
    }
    Job* FirstItem() {
      base::AutoLock lock(mutex_);
      return jobs_.empty() ? nullptr : jobs_.front().get();
    }

    // Also return a held autolock, to ensure the item remains a valid item in
    // the queue while it's in use.
    std::pair<Job*, base::sequence_manager::MoveableAutoLock> LastItem() {
      base::sequence_manager::MoveableAutoLock lock(mutex_);
      Job* job = jobs_.empty() ? nullptr : jobs_.back().get();
      return std::pair<Job*, base::sequence_manager::MoveableAutoLock>(
          job, std::move(lock));
    }

    // Ensure no references are kept to JS objects for a client that is about to
    // be shutdown.
    void PrepareForClientShutdown(web::Context* client);

    // Helper method for PrepareForClientShutdown to help with recursion to
    // equivalent jobs.
    void PrepareJobForClientShutdown(const std::unique_ptr<Job>& job,
                                     web::Context* client);

   private:
    base::Lock mutex_;
    std::deque<std::unique_ptr<Job>> jobs_;
  };

  ServiceWorkerJobs(ServiceWorkerContext* service_worker_context,
                    network::NetworkModule* network_module,
                    base::MessageLoop* message_loop);
  ~ServiceWorkerJobs();

  base::MessageLoop* message_loop() { return message_loop_; }

  // Ensure no references are kept to JS objects for a client that is about to
  // be shutdown.
  void PrepareForClientShutdown(web::Context* client);

  // https://www.w3.org/TR/2022/CRD-service-workers-20220712/#create-job
  std::unique_ptr<Job> CreateJob(
      JobType type, const url::Origin& storage_key, const GURL& scope_url,
      const GURL& script_url,
      std::unique_ptr<script::ValuePromiseWrappable::Reference> promise,
      web::Context* client) {
    return CreateJob(type, storage_key, scope_url, script_url,
                     JobPromiseType::Create(std::move(promise)), client);
  }
  std::unique_ptr<Job> CreateJob(
      JobType type, const url::Origin& storage_key, const GURL& scope_url,
      const GURL& script_url,
      std::unique_ptr<script::ValuePromiseBool::Reference> promise,
      web::Context* client) {
    return CreateJob(type, storage_key, scope_url, script_url,
                     JobPromiseType::Create(std::move(promise)), client);
  }
  std::unique_ptr<Job> CreateJobWithoutPromise(JobType type,
                                               const url::Origin& storage_key,
                                               const GURL& scope_url,
                                               const GURL& script_url) {
    auto job = CreateJob(type, storage_key, scope_url, script_url,
                         std::unique_ptr<JobPromiseType>(), /*client=*/nullptr);
    job->no_promise_okay = true;
    return job;
  }
  std::unique_ptr<Job> CreateJob(
      JobType type, const url::Origin& storage_key, const GURL& scope_url,
      const GURL& script_url, std::unique_ptr<JobPromiseType> promise = nullptr,
      web::Context* client = nullptr);

  // https://www.w3.org/TR/2022/CRD-service-workers-20220712/#schedule-job
  void ScheduleJob(std::unique_ptr<Job> job);

 private:
  friend class ServiceWorkerContext;

  // State used for the 'Update' algorithm.
  struct UpdateJobState : public base::RefCounted<UpdateJobState> {
    UpdateJobState(
        Job* job,
        const scoped_refptr<ServiceWorkerRegistrationObject>& registration,
        ServiceWorkerObject* newest_worker)
        : job(job), registration(registration), newest_worker(newest_worker) {}
    Job* job;
    scoped_refptr<ServiceWorkerRegistrationObject> registration;
    ServiceWorkerObject* newest_worker;

    // Headers received with the main service worker script load.
    scoped_refptr<net::HttpResponseHeaders> script_headers;

    // map of content or resources for the worker.
    ScriptResourceMap updated_resource_map;

    // This represents hasUpdatedResources of the Update algorithm.
    // True if any of the resources has changed since last cached.
    bool has_updated_resources = false;
  };

  // https://www.w3.org/TR/2022/CRD-service-workers-20220712/#dfn-scope-to-job-queue-map
  using JobQueueMap = std::map<std::string, std::unique_ptr<JobQueue>>;

  // Type to hold the errorData for rejection of promises.
  class PromiseErrorData {
   public:
    explicit PromiseErrorData(const script::MessageType& message_type)
        : message_type_(message_type),
          exception_code_(web::DOMException::kNone) {}
    PromiseErrorData(const web::DOMException::ExceptionCode& code,
                     const std::string& message)
        : message_type_(script::kNoError),
          exception_code_(code),
          message_(message) {}

    void Reject(std::unique_ptr<JobPromiseType> promise) const;

   private:
    // Use script::MessageType because it can hold kNoError value to distinguish
    // between simple exceptions and DOM exceptions.
    script::MessageType message_type_;
    const web::DOMException::ExceptionCode exception_code_;
    const std::string message_;
  };

  // https://www.w3.org/TR/2022/CRD-service-workers-20220712/#dfn-job-equivalent
  bool ReturnJobsAreEquivalent(Job* one, Job* two);

  // https://www.w3.org/TR/2022/CRD-service-workers-20220712/#run-job-algorithm
  void RunJob(JobQueue* job_queue);

  // Task for "Run Job" to run in the service worker thread.
  void RunJobTask(JobQueue* job_queue);

  // https://www.w3.org/TR/2022/CRD-service-workers-20220712/#register-algorithm
  void Register(Job* job);

  // https://www.w3.org/TR/2022/CRD-service-workers-20220712/#update-algorithm
  void Update(Job* job);

  void UpdateOnContentProduced(scoped_refptr<UpdateJobState> state,
                               const loader::Origin& last_url_origin,
                               std::unique_ptr<std::string> content);
  bool UpdateOnResponseStarted(
      scoped_refptr<UpdateJobState> state, loader::Fetcher* fetcher,
      const scoped_refptr<net::HttpResponseHeaders>& headers);
  void UpdateOnLoadingComplete(scoped_refptr<UpdateJobState> state,
                               const base::Optional<std::string>& error);

  void UpdateOnRunServiceWorker(scoped_refptr<UpdateJobState> state,
                                scoped_refptr<ServiceWorkerObject> worker,
                                bool run_result);

  // https://www.w3.org/TR/2022/CRD-service-workers-20220712/#unregister-algorithm
  void Unregister(Job* job);

  // https://www.w3.org/TR/2022/CRD-service-workers-20220712/#reject-job-promise
  void RejectJobPromise(Job* job, const PromiseErrorData& error_data);

  // https://www.w3.org/TR/2022/CRD-service-workers-20220712/#resolve-job-promise-algorithm
  void ResolveJobPromise(
      Job* job, const scoped_refptr<ServiceWorkerRegistrationObject>& value) {
    ResolveJobPromise(job, false, value);
  }
  void ResolveJobPromise(Job* job, bool value,
                         const scoped_refptr<ServiceWorkerRegistrationObject>&
                             registration = nullptr);

  // https://www.w3.org/TR/2022/CRD-service-workers-20220712/#finish-job-algorithm
  void FinishJob(Job* job);

  // https://www.w3.org/TR/2022/CRD-service-workers-20220712/#installation-algorithm
  void Install(
      Job* job, const scoped_refptr<ServiceWorkerObject>& worker,
      const scoped_refptr<ServiceWorkerRegistrationObject>& registration);

  ServiceWorkerContext* service_worker_context_;

  // FetcherFactory that is used to create a fetcher according to URL.
  std::unique_ptr<loader::FetcherFactory> fetcher_factory_;
  // LoaderFactory that is used to acquire references to resources from a URL.
  std::unique_ptr<loader::ScriptLoaderFactory> script_loader_factory_;

  base::MessageLoop* message_loop_;

  JobQueueMap job_queue_map_;
};

}  // namespace worker
}  // namespace cobalt

#endif  // COBALT_WORKER_SERVICE_WORKER_JOBS_H_
