// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "core/fetch/DataConsumerHandleTestUtil.h"

#include <memory>
#include "platform/bindings/DOMWrapperWorld.h"
#include "platform/scheduler/child/web_scheduler.h"
#include "public/platform/scheduler/test/renderer_scheduler_test_support.h"

namespace blink {

namespace {

class WaitingHandle final : public WebDataConsumerHandle {
 private:
  class ReaderImpl final : public WebDataConsumerHandle::Reader {
   public:
    WebDataConsumerHandle::Result BeginRead(const void** buffer,
                                            WebDataConsumerHandle::Flags,
                                            size_t* available) override {
      *available = 0;
      *buffer = nullptr;
      return kShouldWait;
    }
    WebDataConsumerHandle::Result EndRead(size_t) override {
      return kUnexpectedError;
    }
  };
  std::unique_ptr<Reader> ObtainReader(Client*) override {
    return std::make_unique<ReaderImpl>();
  }

  const char* DebugName() const override { return "WaitingHandle"; }
};

}  // namespace

DataConsumerHandleTestUtil::Thread::Thread(
    const char* name,
    InitializationPolicy initialization_policy)
    : thread_(WebThreadSupportingGC::Create(name)),
      initialization_policy_(initialization_policy),
      waitable_event_(std::make_unique<WaitableEvent>()) {
  thread_->PostTask(FROM_HERE, CrossThreadBind(&Thread::Initialize,
                                               CrossThreadUnretained(this)));
  waitable_event_->Wait();
}

DataConsumerHandleTestUtil::Thread::~Thread() {
  thread_->PostTask(FROM_HERE, CrossThreadBind(&Thread::Shutdown,
                                               CrossThreadUnretained(this)));
  waitable_event_->Wait();
}

void DataConsumerHandleTestUtil::Thread::Initialize() {
  DCHECK(thread_->IsCurrentThread());
  if (initialization_policy_ >= kScriptExecution) {
    isolate_holder_ = std::make_unique<gin::IsolateHolder>(
        scheduler::GetSingleThreadTaskRunnerForTesting());
    GetIsolate()->Enter();
  }
  thread_->InitializeOnThread();
  if (initialization_policy_ >= kScriptExecution) {
    v8::HandleScope handle_scope(GetIsolate());
    script_state_ = ScriptState::Create(
        v8::Context::New(GetIsolate()),
        DOMWrapperWorld::Create(GetIsolate(),
                                DOMWrapperWorld::WorldType::kTesting));
  }
  if (initialization_policy_ >= kWithExecutionContext) {
    execution_context_ = new NullExecutionContext();
  }
  waitable_event_->Signal();
}

void DataConsumerHandleTestUtil::Thread::Shutdown() {
  DCHECK(thread_->IsCurrentThread());
  execution_context_ = nullptr;
  if (script_state_) {
    script_state_->DisposePerContextData();
  }
  script_state_ = nullptr;
  thread_->ShutdownOnThread();
  if (isolate_holder_) {
    GetIsolate()->Exit();
    GetIsolate()->RequestGarbageCollectionForTesting(
        GetIsolate()->kFullGarbageCollection);
    isolate_holder_ = nullptr;
  }
  waitable_event_->Signal();
}

class DataConsumerHandleTestUtil::ReplayingHandle::ReaderImpl final
    : public Reader {
 public:
  ReaderImpl(scoped_refptr<Context> context, Client* client)
      : context_(std::move(context)) {
    context_->AttachReader(client);
  }
  ~ReaderImpl() override { context_->DetachReader(); }

  WebDataConsumerHandle::Result BeginRead(const void** buffer,
                                          Flags flags,
                                          size_t* available) override {
    return context_->BeginRead(buffer, flags, available);
  }
  WebDataConsumerHandle::Result EndRead(size_t read_size) override {
    return context_->EndRead(read_size);
  }

 private:
  scoped_refptr<Context> context_;
};

void DataConsumerHandleTestUtil::ReplayingHandle::Context::Add(
    const Command& command) {
  MutexLocker locker(mutex_);
  commands_.push_back(command);
}

void DataConsumerHandleTestUtil::ReplayingHandle::Context::AttachReader(
    WebDataConsumerHandle::Client* client) {
  MutexLocker locker(mutex_);
  DCHECK(!reader_thread_);
  DCHECK(!client_);
  reader_thread_ = Platform::Current()->CurrentThread();
  client_ = client;

  if (client_ && !(IsEmpty() && result_ == kShouldWait))
    Notify();
}

void DataConsumerHandleTestUtil::ReplayingHandle::Context::DetachReader() {
  MutexLocker locker(mutex_);
  DCHECK(reader_thread_ && reader_thread_->IsCurrentThread());
  reader_thread_ = nullptr;
  client_ = nullptr;
  if (!is_handle_attached_)
    detached_->Signal();
}

void DataConsumerHandleTestUtil::ReplayingHandle::Context::DetachHandle() {
  MutexLocker locker(mutex_);
  is_handle_attached_ = false;
  if (!reader_thread_)
    detached_->Signal();
}

WebDataConsumerHandle::Result
DataConsumerHandleTestUtil::ReplayingHandle::Context::BeginRead(
    const void** buffer,
    Flags,
    size_t* available) {
  MutexLocker locker(mutex_);
  *buffer = nullptr;
  *available = 0;
  if (IsEmpty())
    return result_;

  const Command& command = Top();
  WebDataConsumerHandle::Result result = kOk;
  switch (command.GetName()) {
    case Command::kData: {
      auto& body = command.Body();
      *available = body.size() - Offset();
      *buffer = body.data() + Offset();
      result = kOk;
      break;
    }
    case Command::kDone:
      result_ = result = kDone;
      Consume(0);
      break;
    case Command::kWait:
      Consume(0);
      result = kShouldWait;
      Notify();
      break;
    case Command::kError:
      result_ = result = kUnexpectedError;
      Consume(0);
      break;
  }
  return result;
}

WebDataConsumerHandle::Result
DataConsumerHandleTestUtil::ReplayingHandle::Context::EndRead(
    size_t read_size) {
  MutexLocker locker(mutex_);
  Consume(read_size);
  return kOk;
}

DataConsumerHandleTestUtil::ReplayingHandle::Context::Context()
    : offset_(0),
      reader_thread_(nullptr),
      client_(nullptr),
      result_(kShouldWait),
      is_handle_attached_(true),
      detached_(std::make_unique<WaitableEvent>()) {}

const DataConsumerHandleTestUtil::Command&
DataConsumerHandleTestUtil::ReplayingHandle::Context::Top() {
  DCHECK(!IsEmpty());
  return commands_.front();
}

void DataConsumerHandleTestUtil::ReplayingHandle::Context::Consume(
    size_t size) {
  DCHECK(!IsEmpty());
  DCHECK(size + offset_ <= Top().Body().size());
  bool fully_consumed = (size + offset_ >= Top().Body().size());
  if (fully_consumed) {
    offset_ = 0;
    commands_.pop_front();
  } else {
    offset_ += size;
  }
}

void DataConsumerHandleTestUtil::ReplayingHandle::Context::Notify() {
  if (!client_)
    return;
  DCHECK(reader_thread_);
  PostCrossThreadTask(
      *reader_thread_->GetWebTaskRunner(), FROM_HERE,
      CrossThreadBind(&Context::NotifyInternal, WrapRefCounted(this)));
}

void DataConsumerHandleTestUtil::ReplayingHandle::Context::NotifyInternal() {
  {
    MutexLocker locker(mutex_);
    if (!client_ || !reader_thread_->IsCurrentThread()) {
      // There is no client, or a new reader is attached.
      return;
    }
  }
  // The reading thread is the current thread.
  client_->DidGetReadable();
}

DataConsumerHandleTestUtil::ReplayingHandle::ReplayingHandle()
    : context_(Context::Create()) {}

DataConsumerHandleTestUtil::ReplayingHandle::~ReplayingHandle() {
  context_->DetachHandle();
}

std::unique_ptr<WebDataConsumerHandle::Reader>
DataConsumerHandleTestUtil::ReplayingHandle::ObtainReader(Client* client) {
  return std::make_unique<ReaderImpl>(context_, client);
}

void DataConsumerHandleTestUtil::ReplayingHandle::Add(const Command& command) {
  context_->Add(command);
}

std::unique_ptr<WebDataConsumerHandle>
DataConsumerHandleTestUtil::CreateWaitingDataConsumerHandle() {
  return std::make_unique<WaitingHandle>();
}

}  // namespace blink
