// Copyright 2018 Google Inc. 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 "base/message_loop/message_pump_ui_starboard.h"

#include "base/logging.h"
#include "base/time/time.h"
#include "starboard/event.h"
#include "starboard/system.h"

namespace base {

namespace {

void CallMessagePumpImmediate(void* context) {
  DCHECK(context);
  MessagePumpUIStarboard* pump =
      reinterpret_cast<MessagePumpUIStarboard*>(context);
  pump->CancelImmediate();
  pump->RunUntilIdle();
}

void CallMessagePumpDelayed(void* context) {
  DCHECK(context);
  MessagePumpUIStarboard* pump =
      reinterpret_cast<MessagePumpUIStarboard*>(context);
  pump->CancelDelayed();
  pump->RunUntilIdle();
}

}  // namespace

MessagePumpUIStarboard::MessagePumpUIStarboard() : delegate_(nullptr) {}

void MessagePumpUIStarboard::CancelDelayed() {
  base::AutoLock auto_lock(outstanding_events_lock_);
  CancelDelayedLocked();
}

void MessagePumpUIStarboard::CancelImmediate() {
  base::AutoLock auto_lock(outstanding_events_lock_);
  CancelImmediateLocked();
}

void MessagePumpUIStarboard::RunUntilIdle() {
  DCHECK(delegate_);
#if !defined(COBALT_BUILD_TYPE_GOLD)
  // Abort if this is a QA build to signal that this is unexpected.
  CHECK(delegate_);
#endif

  if (should_quit())
    return;

  for (;;) {
    // Do some work and see if the next task is ready right away.
    Delegate::NextWorkInfo next_work_info = delegate_->DoWork();
    bool attempt_more_work = next_work_info.is_immediate();

    if (should_quit())
      break;

    if (attempt_more_work)
      continue;

    attempt_more_work = delegate_->DoIdleWork();

    if (should_quit())
      break;

    if (attempt_more_work)
      continue;

    // If there is delayed work.
    if (!next_work_info.delayed_run_time.is_max()) {
      ScheduleDelayedWork(next_work_info);
    }

    // Idle.
    break;
  }
}

void MessagePumpUIStarboard::Run(Delegate* delegate) {
  // This should never be called because we are not like a normal message pump
  // where we loop until told to quit. We are providing a MessagePump interface
  // on top of an externally-owned message pump. We want to exist and be able to
  // schedule work, but the actual for(;;) loop is owned by Starboard.
  NOTREACHED();
}

void MessagePumpUIStarboard::Attach(Delegate* delegate) {
  // Since the Looper is controlled by the UI thread or JavaHandlerThread, we
  // can't use Run() like we do on other platforms or we would prevent Java
  // tasks from running. Instead we create and initialize a run loop here, then
  // return control back to the Looper.

  SetDelegate(delegate);
}

void MessagePumpUIStarboard::Quit() {
  delegate_ = nullptr;
  CancelAll();
}

void MessagePumpUIStarboard::ScheduleWork() {
  // Check if outstanding event already exists.
  if (outstanding_event_)
    return;

  base::AutoLock auto_lock(outstanding_events_lock_);
  outstanding_event_ =
      SbEventSchedule(&CallMessagePumpImmediate, this, 0);
}

void MessagePumpUIStarboard::ScheduleDelayedWork(
    const Delegate::NextWorkInfo& next_work_info) {
  if (next_work_info.is_immediate() || next_work_info.delayed_run_time.is_max()) {
    return;
  }

  TimeDelta delay = next_work_info.remaining_delay();
  if (delay.is_negative()) {
    delay = base::TimeDelta();
  }

  base::AutoLock auto_lock(outstanding_events_lock_);
  // Make sure any outstanding delayed event is canceled.
  CancelDelayedLocked();
  outstanding_delayed_event_ =
      SbEventSchedule(&CallMessagePumpDelayed, this, delay.InMicroseconds());
}

void MessagePumpUIStarboard::CancelAll() {
  base::AutoLock auto_lock(outstanding_events_lock_);
  CancelImmediateLocked();
  CancelDelayedLocked();
}

void MessagePumpUIStarboard::CancelImmediateLocked() {
  outstanding_events_lock_.AssertAcquired();
  if (!outstanding_event_)
    return;

  SbEventCancel(*outstanding_event_);
  outstanding_event_.reset();
}

void MessagePumpUIStarboard::CancelDelayedLocked() {
  outstanding_events_lock_.AssertAcquired();
  if (!outstanding_delayed_event_)
    return;

  SbEventCancel(*outstanding_delayed_event_);
  outstanding_delayed_event_.reset();
}

MessagePump::Delegate* MessagePumpForUI::SetDelegate(Delegate* delegate) {
  return std::exchange(delegate_, delegate);
}

}  // namespace base
