// 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_WEB_TESTING_STUB_WEB_CONTEXT_H_
#define COBALT_WEB_TESTING_STUB_WEB_CONTEXT_H_

#include <memory>
#include <string>

#include "base/message_loop/message_loop.h"
#include "base/test/scoped_task_environment.h"
#include "cobalt/loader/fetcher_factory.h"
#include "cobalt/network/network_module.h"
#include "cobalt/script/global_environment.h"
#include "cobalt/script/javascript_engine.h"
#include "cobalt/script/wrappable.h"
#include "cobalt/web/blob.h"
#include "cobalt/web/context.h"
#include "cobalt/web/environment_settings.h"
#include "cobalt/web/testing/mock_user_agent_platform_info.h"
#include "cobalt/web/testing/stub_environment_settings.h"
#include "cobalt/web/url.h"
#include "cobalt/web/user_agent_platform_info.h"
#include "cobalt/worker/service_worker.h"
#include "cobalt/worker/service_worker_object.h"
#include "cobalt/worker/service_worker_registration.h"
#include "url/gurl.h"

namespace cobalt {
namespace loader {
class FetcherFactory;
class ScriptLoaderFactory;
}  // namespace loader
namespace web {
namespace testing {

class StubWebContext final : public Context {
 public:
  StubWebContext() : Context(), name_("StubWebInstance") {
    javascript_engine_ = script::JavaScriptEngine::CreateEngine();
    global_environment_ = javascript_engine_->CreateGlobalEnvironment();
    blob_registry_.reset(new Blob::Registry);
    network_module_.reset(new network::NetworkModule());
    fetcher_factory_.reset(new loader::FetcherFactory(
        network_module_.get(),
        URL::MakeBlobResolverCallback(blob_registry_.get())));
  }
  ~StubWebContext() final { blob_registry_.reset(); }

  void AddEnvironmentSettingsChangeObserver(
      Context::EnvironmentSettingsChangeObserver* observer) final {}
  void RemoveEnvironmentSettingsChangeObserver(
      Context::EnvironmentSettingsChangeObserver* observer) final {}

  // WebInstance
  //
  base::MessageLoop* message_loop() const final {
    return base::MessageLoop::current();
  }
  void ShutDownJavaScriptEngine() final { NOTREACHED(); }
  loader::FetcherFactory* fetcher_factory() const final {
    DCHECK(fetcher_factory_);
    return fetcher_factory_.get();
  }

  loader::ScriptLoaderFactory* script_loader_factory() const final {
    DCHECK(script_loader_factory_);
    return script_loader_factory_.get();
  }

  script::JavaScriptEngine* javascript_engine() const final {
    DCHECK(javascript_engine_);
    return javascript_engine_.get();
  }
  script::GlobalEnvironment* global_environment() const final {
    DCHECK(global_environment_);
    return global_environment_.get();
  }
  script::ExecutionState* execution_state() const final {
    NOTREACHED();
    return nullptr;
  }
  script::ScriptRunner* script_runner() const final {
    NOTREACHED();
    return nullptr;
  }
  Blob::Registry* blob_registry() const final {
    DCHECK(blob_registry_);
    return blob_registry_.get();
  }
  network::NetworkModule* network_module() const final {
    DCHECK(network_module_);
    return network_module_.get();
  }

  worker::ServiceWorkerJobs* service_worker_jobs() const final {
    NOTREACHED();
    return nullptr;
  }

  const std::string& name() const final { return name_; };
  void setup_environment_settings(
      EnvironmentSettings* environment_settings) final {
    environment_settings_.reset(environment_settings);
    if (environment_settings_) environment_settings_->set_context(this);
  }
  EnvironmentSettings* environment_settings() const final {
    return environment_settings_.get();
  }
  EnvironmentSettings* setup_stub_environment_settings() {
    setup_environment_settings(new testing::StubEnvironmentSettings);
    return environment_settings();
  }

  scoped_refptr<worker::ServiceWorkerRegistration>
  LookupServiceWorkerRegistration(
      worker::ServiceWorkerRegistrationObject* registration) final {
    NOTIMPLEMENTED();
    return scoped_refptr<worker::ServiceWorkerRegistration>();
  }
  scoped_refptr<worker::ServiceWorkerRegistration> GetServiceWorkerRegistration(
      worker::ServiceWorkerRegistrationObject* registration) final {
    NOTIMPLEMENTED();
    return scoped_refptr<worker::ServiceWorkerRegistration>();
  }

  void RemoveServiceWorker(worker::ServiceWorkerObject* worker) final {
    NOTIMPLEMENTED();
  }
  scoped_refptr<worker::ServiceWorker> LookupServiceWorker(
      worker::ServiceWorkerObject* worker) final {
    NOTIMPLEMENTED();
    return scoped_refptr<worker::ServiceWorker>();
  }
  scoped_refptr<worker::ServiceWorker> GetServiceWorker(
      worker::ServiceWorkerObject* worker) final {
    NOTIMPLEMENTED();
    return scoped_refptr<worker::ServiceWorker>();
  }

  WindowOrWorkerGlobalScope* GetWindowOrWorkerGlobalScope() final {
    script::Wrappable* global_wrappable =
        global_environment()->global_wrappable();
    if (!global_wrappable) {
      return nullptr;
    }
    DCHECK(global_wrappable->IsWrappable());
    DCHECK_EQ(script::Wrappable::JSObjectType::kObject,
              global_wrappable->GetJSObjectType());

    return base::polymorphic_downcast<WindowOrWorkerGlobalScope*>(
        global_wrappable);
  }

  void set_platform_info(UserAgentPlatformInfo* platform_info) {
    platform_info_ = platform_info;
  }
  const UserAgentPlatformInfo* platform_info() const final {
    return (platform_info_ ? platform_info_ : &mock_platform_info_);
  }

  std::string GetUserAgent() const final {
    return std::string("StubUserAgentString");
  }
  std::string GetPreferredLanguage() const final {
    return std::string("StubPreferredLanguageString");
  }

  bool is_controlled_by(worker::ServiceWorkerObject* worker) const final {
    NOTIMPLEMENTED();
    return false;
  }

  void set_active_service_worker(
      const scoped_refptr<worker::ServiceWorkerObject>& worker) {
    service_worker_object_ = worker;
  }
  scoped_refptr<worker::ServiceWorkerObject>& active_service_worker() final {
    return service_worker_object_;
  }
  const scoped_refptr<worker::ServiceWorkerObject>& active_service_worker()
      const final {
    return service_worker_object_;
  }

  // Other
 private:
  // Name of the web instance.
  const std::string name_;

  base::test::ScopedTaskEnvironment env_;

  std::unique_ptr<loader::FetcherFactory> fetcher_factory_;
  std::unique_ptr<Blob::Registry> blob_registry_;
  std::unique_ptr<loader::ScriptLoaderFactory> script_loader_factory_;
  std::unique_ptr<script::JavaScriptEngine> javascript_engine_;
  scoped_refptr<script::GlobalEnvironment> global_environment_;

  std::unique_ptr<network::NetworkModule> network_module_;
  // Environment Settings object
  std::unique_ptr<EnvironmentSettings> environment_settings_;
  UserAgentPlatformInfo* platform_info_ = nullptr;
  scoped_refptr<worker::ServiceWorkerObject> service_worker_object_;
  MockUserAgentPlatformInfo mock_platform_info_;
};

}  // namespace testing
}  // namespace web
}  // namespace cobalt

#endif  // COBALT_WEB_TESTING_STUB_WEB_CONTEXT_H_
