// 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 <stddef.h>
#include <windows.h>
#include <mmsystem.h>

#include "base/event_recorder.h"
#include "base/file_util.h"
#include "base/logging.h"

// A note about time.
// For perfect playback of events, you'd like a very accurate timer
// so that events are played back at exactly the same time that
// they were recorded.  However, windows has a clock which is only
// granular to ~15ms.  We see more consistent event playback when
// using a higher resolution timer.  To do this, we use the
// timeGetTime API instead of the default GetTickCount() API.

namespace base {

EventRecorder* EventRecorder::current_ = NULL;

LRESULT CALLBACK StaticRecordWndProc(int nCode, WPARAM wParam,
                                     LPARAM lParam) {
  DCHECK(EventRecorder::current());
  return EventRecorder::current()->RecordWndProc(nCode, wParam, lParam);
}

LRESULT CALLBACK StaticPlaybackWndProc(int nCode, WPARAM wParam,
                                       LPARAM lParam) {
  DCHECK(EventRecorder::current());
  return EventRecorder::current()->PlaybackWndProc(nCode, wParam, lParam);
}

EventRecorder::~EventRecorder() {
  // Try to assert early if the caller deletes the recorder
  // while it is still in use.
  DCHECK(!journal_hook_);
  DCHECK(!is_recording_ && !is_playing_);
}

bool EventRecorder::StartRecording(const FilePath& filename) {
  if (journal_hook_ != NULL)
    return false;
  if (is_recording_ || is_playing_)
    return false;

  // Open the recording file.
  DCHECK(!file_);
  file_ = file_util::OpenFile(filename, "wb+");
  if (!file_) {
    DLOG(ERROR) << "EventRecorder could not open log file";
    return false;
  }

  // Set the faster clock, if possible.
  ::timeBeginPeriod(1);

  // Set the recording hook.  JOURNALRECORD can only be used as a global hook.
  journal_hook_ = ::SetWindowsHookEx(WH_JOURNALRECORD, StaticRecordWndProc,
                                     GetModuleHandle(NULL), 0);
  if (!journal_hook_) {
    DLOG(ERROR) << "EventRecorder Record Hook failed";
    file_util::CloseFile(file_);
    return false;
  }

  is_recording_ = true;
  return true;
}

void EventRecorder::StopRecording() {
  if (is_recording_) {
    DCHECK(journal_hook_ != NULL);

    if (!::UnhookWindowsHookEx(journal_hook_)) {
      DLOG(ERROR) << "EventRecorder Unhook failed";
      // Nothing else we can really do here.
      return;
    }

    ::timeEndPeriod(1);

    DCHECK(file_ != NULL);
    file_util::CloseFile(file_);
    file_ = NULL;

    journal_hook_ = NULL;
    is_recording_ = false;
  }
}

bool EventRecorder::StartPlayback(const FilePath& filename) {
  if (journal_hook_ != NULL)
    return false;
  if (is_recording_ || is_playing_)
    return false;

  // Open the recording file.
  DCHECK(!file_);
  file_ = file_util::OpenFile(filename, "rb");
  if (!file_) {
    DLOG(ERROR) << "EventRecorder Playback could not open log file";
    return false;
  }
  // Read the first event from the record.
  if (fread(&playback_msg_, sizeof(EVENTMSG), 1, file_) != 1) {
    DLOG(ERROR) << "EventRecorder Playback has no records!";
    file_util::CloseFile(file_);
    return false;
  }

  // Set the faster clock, if possible.
  ::timeBeginPeriod(1);

  // Playback time is tricky.  When playing back, we read a series of events,
  // each with timeouts.  Simply subtracting the delta between two timers will
  // lead to fast playback (about 2x speed).  The API has two events, one
  // which advances to the next event (HC_SKIP), and another that requests the
  // event (HC_GETNEXT).  The same event will be requested multiple times.
  // Each time the event is requested, we must calculate the new delay.
  // To do this, we track the start time of the playback, and constantly
  // re-compute the delay.   I mention this only because I saw two examples
  // of how to use this code on the net, and both were broken :-)
  playback_start_time_ = timeGetTime();
  playback_first_msg_time_ = playback_msg_.time;

  // Set the hook.  JOURNALPLAYBACK can only be used as a global hook.
  journal_hook_ = ::SetWindowsHookEx(WH_JOURNALPLAYBACK, StaticPlaybackWndProc,
                                     GetModuleHandle(NULL), 0);
  if (!journal_hook_) {
    DLOG(ERROR) << "EventRecorder Playback Hook failed";
    return false;
  }

  is_playing_ = true;

  return true;
}

void EventRecorder::StopPlayback() {
  if (is_playing_) {
    DCHECK(journal_hook_ != NULL);

    if (!::UnhookWindowsHookEx(journal_hook_)) {
      DLOG(ERROR) << "EventRecorder Unhook failed";
      // Nothing else we can really do here.
    }

    DCHECK(file_ != NULL);
    file_util::CloseFile(file_);
    file_ = NULL;

    ::timeEndPeriod(1);

    journal_hook_ = NULL;
    is_playing_ = false;
  }
}

// Windows callback hook for the recorder.
LRESULT EventRecorder::RecordWndProc(int nCode, WPARAM wParam, LPARAM lParam) {
  static bool recording_enabled = true;
  EVENTMSG* msg_ptr = NULL;

  // The API says we have to do this.
  // See http://msdn2.microsoft.com/en-us/library/ms644983(VS.85).aspx
  if (nCode < 0)
    return ::CallNextHookEx(journal_hook_, nCode, wParam, lParam);

  // Check for the break key being pressed and stop recording.
  if (::GetKeyState(VK_CANCEL) & 0x8000) {
    StopRecording();
    return ::CallNextHookEx(journal_hook_, nCode, wParam, lParam);
  }

  // The Journal Recorder must stop recording events when system modal
  // dialogs are present. (see msdn link above)
  switch (nCode) {
    case HC_SYSMODALON:
      recording_enabled = false;
      break;
    case HC_SYSMODALOFF:
      recording_enabled = true;
      break;
  }

  if (nCode == HC_ACTION && recording_enabled) {
    // Aha - we have an event to record.
    msg_ptr = reinterpret_cast<EVENTMSG*>(lParam);
    msg_ptr->time = timeGetTime();
    fwrite(msg_ptr, sizeof(EVENTMSG), 1, file_);
    fflush(file_);
  }

  return CallNextHookEx(journal_hook_, nCode, wParam, lParam);
}

// Windows callback for the playback mode.
LRESULT EventRecorder::PlaybackWndProc(int nCode, WPARAM wParam,
                                       LPARAM lParam) {
  static bool playback_enabled = true;
  int delay = 0;

  switch (nCode) {
    // A system modal dialog box is being displayed.  Stop playing back
    // messages.
    case HC_SYSMODALON:
      playback_enabled = false;
      break;

    // A system modal dialog box is destroyed.  We can start playing back
    // messages again.
    case HC_SYSMODALOFF:
      playback_enabled = true;
      break;

    // Prepare to copy the next mouse or keyboard event to playback.
    case HC_SKIP:
      if (!playback_enabled)
        break;

      // Read the next event from the record.
      if (fread(&playback_msg_, sizeof(EVENTMSG), 1, file_) != 1)
        this->StopPlayback();
      break;

    // Copy the mouse or keyboard event to the EVENTMSG structure in lParam.
    case HC_GETNEXT:
      if (!playback_enabled)
        break;

      memcpy(reinterpret_cast<void*>(lParam), &playback_msg_,
             sizeof(playback_msg_));

      // The return value is the amount of time (in milliseconds) to wait
      // before playing back the next message in the playback queue.  Each
      // time this is called, we recalculate the delay relative to our current
      // wall clock.
      delay = (playback_msg_.time - playback_first_msg_time_) -
              (timeGetTime() - playback_start_time_);
      if (delay < 0)
        delay = 0;
      return delay;

    // An application has called PeekMessage with wRemoveMsg set to PM_NOREMOVE
    // indicating that the message is not removed from the message queue after
    // PeekMessage processing.
    case HC_NOREMOVE:
      break;
  }

  return CallNextHookEx(journal_hook_, nCode, wParam, lParam);
}

}  // namespace base
