// Copyright 2018 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 <memory>

#include "cobalt/base/polymorphic_downcast.h"
#include "cobalt/script/v8c/cobalt_platform.h"

#include "base/logging.h"

namespace cobalt {
namespace script {
namespace v8c {

CobaltPlatform::CobaltV8TaskRunner::CobaltV8TaskRunner()
    : ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {}

void CobaltPlatform::CobaltV8TaskRunner::PostTask(
    std::unique_ptr<v8::Task> task) {
  PostDelayedTask(std::move(task), 0);
}

void CobaltPlatform::CobaltV8TaskRunner::PostDelayedTask(
    std::unique_ptr<v8::Task> task, double delay_in_seconds) {
  base::AutoLock auto_lock(lock_);
  if (task_runner_) {
    task_runner_->PostDelayedTask(
        FROM_HERE,
        base::Bind(&CobaltPlatform::CobaltV8TaskRunner::RunV8Task,
                   weak_ptr_factory_.GetWeakPtr(), base::Passed(&task)),
        base::TimeDelta::FromSecondsD(delay_in_seconds));
  } else {
    tasks_before_registration_.push_back(
        std::unique_ptr<TaskBeforeRegistration>(
            new TaskBeforeRegistration(delay_in_seconds, std::move(task))));
  }
}

void CobaltPlatform::CobaltV8TaskRunner::SetTaskRunner(
    base::SingleThreadTaskRunner* task_runner) {
  base::AutoLock auto_lock(lock_);
  task_runner_ = task_runner;
  DCHECK(task_runner);
  for (unsigned int i = 0; i < tasks_before_registration_.size(); ++i) {
    std::unique_ptr<v8::Task> scoped_task =
        std::move(tasks_before_registration_[i]->task);
    base::TimeDelta delay = std::max(
        tasks_before_registration_[i]->target_time - base::TimeTicks::Now(),
        base::TimeDelta::FromSeconds(0));
    task_runner_->PostDelayedTask(
        FROM_HERE,
        base::Bind(&CobaltPlatform::CobaltV8TaskRunner::RunV8Task,
                   weak_ptr_factory_.GetWeakPtr(), base::Passed(&scoped_task)),
        delay);
  }
  tasks_before_registration_.clear();
}

void CobaltPlatform::CobaltV8TaskRunner::RunV8Task(
    std::unique_ptr<v8::Task> task) {
  task->Run();
}

std::shared_ptr<v8::TaskRunner> CobaltPlatform::GetForegroundTaskRunner(
    v8::Isolate* isolate) {
  base::AutoLock auto_lock(lock_);
  std::shared_ptr<CobaltPlatform::CobaltV8TaskRunner> task_runner;
  if (v8_task_runner_map_.find(isolate) == v8_task_runner_map_.end()) {
    task_runner = std::make_shared<CobaltPlatform::CobaltV8TaskRunner>();
    v8_task_runner_map_.emplace(isolate, task_runner);
  } else {
    task_runner = v8_task_runner_map_[isolate];
  }
  DCHECK(task_runner);
  return task_runner;
}

void CobaltPlatform::RegisterIsolateOnThread(v8::Isolate* isolate,
                                             base::MessageLoop* message_loop) {
  auto task_runner = GetForegroundTaskRunner(isolate);
  CobaltPlatform::CobaltV8TaskRunner* cobalt_v8_task_runner =
      base::polymorphic_downcast<CobaltPlatform::CobaltV8TaskRunner*>(
          task_runner.get());
  cobalt_v8_task_runner->SetTaskRunner(message_loop->task_runner().get());
}

void CobaltPlatform::UnregisterIsolateOnThread(v8::Isolate* isolate) {
  base::AutoLock auto_lock(lock_);
  auto iter = v8_task_runner_map_.find(isolate);
  if (iter != v8_task_runner_map_.end()) {
    v8_task_runner_map_.erase(iter);
  } else {
    DLOG(WARNING) << "Isolate is not in the map and can not be unregistered.";
  }
}

void CobaltPlatform::CallOnForegroundThread(v8::Isolate* isolate,
                                            v8::Task* task) {
  GetForegroundTaskRunner(isolate)->PostTask(std::unique_ptr<v8::Task>(task));
}

void CobaltPlatform::CallDelayedOnForegroundThread(v8::Isolate* isolate,
                                                   v8::Task* task,
                                                   double delay_in_seconds) {
  GetForegroundTaskRunner(isolate)->PostDelayedTask(
      std::unique_ptr<v8::Task>(task), delay_in_seconds);
}

}  // namespace v8c
}  // namespace script
}  // namespace cobalt
