// Copyright (c) 2011 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 "chrome_frame/task_marshaller.h"

#include "base/callback.h"
#include "base/logging.h"

TaskMarshallerThroughMessageQueue::TaskMarshallerThroughMessageQueue()
    : wnd_(NULL),
      msg_(0xFFFF) {
}

TaskMarshallerThroughMessageQueue::~TaskMarshallerThroughMessageQueue() {
  ClearTasks();
}

void TaskMarshallerThroughMessageQueue::PostTask(
    const tracked_objects::Location& from_here, const base::Closure& task) {
  DCHECK(wnd_ != NULL);

  lock_.Acquire();
  bool has_work = !pending_tasks_.empty();
  pending_tasks_.push(task);
  lock_.Release();

  // Don't post message if there is already one.
  if (has_work)
    return;

  if (!::PostMessage(wnd_, msg_, 0, 0)) {
    DVLOG(1) << "Dropping MSG_EXECUTE_TASK message for destroyed window.";
    ClearTasks();
  }
}

void TaskMarshallerThroughMessageQueue::PostDelayedTask(
    const tracked_objects::Location& source,
    const base::Closure& task,
    base::TimeDelta& delay) {
  DCHECK(wnd_);

  base::AutoLock lock(lock_);
  base::PendingTask delayed_task(source, task, base::TimeTicks::Now() + delay,
                                 true);
  base::TimeTicks top_run_time = delayed_tasks_.top().delayed_run_time;
  delayed_tasks_.push(delayed_task);

  // Reschedule the timer if |delayed_task| will be the next delayed task to
  // run.
  if (delayed_task.delayed_run_time < top_run_time) {
    ::SetTimer(wnd_, reinterpret_cast<UINT_PTR>(this),
               static_cast<DWORD>(delay.InMilliseconds()), NULL);
  }
}

BOOL TaskMarshallerThroughMessageQueue::ProcessWindowMessage(HWND hWnd,
                                                             UINT uMsg,
                                                             WPARAM wParam,
                                                             LPARAM lParam,
                                                             LRESULT& lResult,
                                                             DWORD dwMsgMapID) {
  if (hWnd == wnd_ && uMsg == msg_) {
    ExecuteQueuedTasks();
    lResult = 0;
    return TRUE;
  }

  if (hWnd == wnd_ && uMsg == WM_TIMER) {
    ExecuteDelayedTasks();
    lResult = 0;
    return TRUE;
  }

  return FALSE;
}

base::Closure TaskMarshallerThroughMessageQueue::PopTask() {
  base::AutoLock lock(lock_);
  if (pending_tasks_.empty())
    return base::Closure();

  base::Closure task = pending_tasks_.front();
  pending_tasks_.pop();
  return task;
}

void TaskMarshallerThroughMessageQueue::ExecuteQueuedTasks() {
  DCHECK(CalledOnValidThread());
  base::Closure task;
  while (!(task = PopTask()).is_null())
    task.Run();
}

void TaskMarshallerThroughMessageQueue::ExecuteDelayedTasks() {
  DCHECK(CalledOnValidThread());
  ::KillTimer(wnd_, reinterpret_cast<UINT_PTR>(this));
  while (true) {
    lock_.Acquire();

    if (delayed_tasks_.empty()) {
      lock_.Release();
      return;
    }

    base::PendingTask next_task = delayed_tasks_.top();
    base::TimeTicks now = base::TimeTicks::Now();
    base::TimeTicks next_run = next_task.delayed_run_time;
    if (next_run > now) {
      int64 delay = (next_run - now).InMillisecondsRoundedUp();
      ::SetTimer(wnd_, reinterpret_cast<UINT_PTR>(this),
                 static_cast<DWORD>(delay), NULL);
      lock_.Release();
      return;
    }

    delayed_tasks_.pop();
    lock_.Release();

    // Run the task outside the lock.
    next_task.task.Run();
  }
}

void TaskMarshallerThroughMessageQueue::ClearTasks() {
  base::AutoLock lock(lock_);
  DVLOG_IF(1, !pending_tasks_.empty()) << "Destroying "
                                       << pending_tasks_.size()
                                       << " pending tasks.";
  while (!pending_tasks_.empty())
    pending_tasks_.pop();

  while (!delayed_tasks_.empty())
    delayed_tasks_.pop();
}
