// 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_H_
#define COBALT_WORKER_SERVICE_WORKER_H_

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

#include "cobalt/script/environment_settings.h"
#include "cobalt/script/wrappable.h"
#include "cobalt/web/event_target.h"
#include "cobalt/web/event_target_listener_info.h"
#include "cobalt/web/message_port.h"
#include "cobalt/worker/abstract_worker.h"
#include "cobalt/worker/service_worker_object.h"
#include "cobalt/worker/service_worker_state.h"

namespace cobalt {
namespace worker {

// The ServiceWorker interface represents a service worker within a service
// worker client realm.
//   https://w3c.github.io/ServiceWorker/#serviceworker-interface
class ServiceWorker : public AbstractWorker, public web::EventTarget {
 public:
  ServiceWorker(script::EnvironmentSettings* settings,
                ServiceWorkerObject* worker);
  ServiceWorker(const ServiceWorker&) = delete;
  ServiceWorker& operator=(const ServiceWorker&) = delete;

  // Web API: ServiceWorker
  //
  void PostMessage(const std::string& message) {
    DCHECK(message_port_);
    message_port_->PostMessage(message);
  }

  // The scriptURL getter steps are to return the
  // service worker's serialized script url.
  std::string script_url() const { return worker_->script_url().spec(); }

  // https://w3c.github.io/ServiceWorker/#dom-serviceworker-state
  void set_state(ServiceWorkerState state) { state_ = state; }
  ServiceWorkerState state() const { return state_; }

  const EventListenerScriptValue* onstatechange() const {
    return GetAttributeEventListener(base::Tokens::statechange());
  }
  void set_onstatechange(const EventListenerScriptValue& event_listener) {
    SetAttributeEventListener(base::Tokens::statechange(), event_listener);
  }

  // Web API: Abstract Worker
  //
  const EventListenerScriptValue* onerror() const override {
    return GetAttributeEventListener(base::Tokens::error());
  }
  void set_onerror(const EventListenerScriptValue& event_listener) override {
    SetAttributeEventListener(base::Tokens::error(), event_listener);
  }

  ServiceWorkerObject* service_worker_object() { return worker_; }

  DEFINE_WRAPPABLE_TYPE(ServiceWorker);

 private:
  ~ServiceWorker() override {
    message_port_.reset();
    worker_ = nullptr;
  }

  ServiceWorkerObject* worker_ = nullptr;
  scoped_refptr<web::MessagePort> message_port_;
  ServiceWorkerState state_;
};

}  // namespace worker
}  // namespace cobalt

#endif  // COBALT_WORKER_SERVICE_WORKER_H_
