// 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_ = 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";
    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);
    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_ = 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!";
    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);
    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
