/*
Copyright 2007-2009 WebDriver committers
Copyright 2007-2009 Google Inc.

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 <ctime>
#include <string>
#include <iostream>
#include <fstream>

#include "interactions.h"
#include "logging.h"

#include <gdk/gdk.h>
#include <gdk/gdkkeysyms.h>
#include <X11/Xlib.h>
#include <time.h>
#include <stdlib.h>
#include <assert.h>
#include <list>
#include <algorithm>
#include <functional>

#include "translate_keycode_linux.h"
#include "interactions_linux.h"

using namespace std;

// This class represents a single modifier key. A modifier key is Shift,
// Ctrl or Alt. A key has, besides a GDK symbol related to it, a Mask
// that must be appended to each keyboard event when this modifier is
// set.
class XModifierKey
{
 public:
  // Stores the key associated with this modifier and the bit-mask
  // to set when this key was toggled.
  XModifierKey(const guint& associated_gdk_key, const GdkModifierType& gdk_mod,
    const guint32& stored_state);
  // if a_key matches the associated gdk key, toggeles the modifier
  // key state.
  void ToggleIfKeyMatches(const guint a_key);
  // Returns true if the key given matches the key associated with
  // this modifier.
  bool KeyMatches(const guint a_key) const;
  // if the modifier key was pressed, return the mask to OR with.
  // If not, return 0.
  guint GetAppropriateMask() const;
  // Set the modifier to false.
  void ClearModifier();
  // Returns the associated key
  guint get_associated_key() const;
  // Returns true if the modifier is set, false otherwise.
  bool get_toggle() const;
  // Store the current state of the modifier key into the provided int.
  void StoreState(guint32* state_store) const;
 private:
  bool toggle_;
  guint associated_key_;
  GdkModifierType gdk_mod_mask_;
};

XModifierKey::XModifierKey(const guint& associated_gdk_key,
                           const GdkModifierType& gdk_mod,
                           const guint32& stored_state) :
  toggle_(stored_state & gdk_mod), associated_key_(associated_gdk_key), gdk_mod_mask_(gdk_mod)
{
  LOG(DEBUG) << "Restored state for " << gdk_mod_mask_ << " : " << toggle_;
}

bool XModifierKey::KeyMatches(const guint a_key) const
{
  return (a_key == associated_key_);
}

void XModifierKey::ToggleIfKeyMatches(const guint a_key)
{
  if (KeyMatches(a_key)) {
    toggle_ = !toggle_;
  }
}

guint XModifierKey::GetAppropriateMask() const
{
  if (toggle_) {
    return gdk_mod_mask_;
  }
  return 0;
}

guint XModifierKey::get_associated_key() const
{
  return associated_key_;
}

void XModifierKey::ClearModifier()
{
  toggle_ = false;
}

bool XModifierKey::get_toggle() const
{
  return toggle_;
}

void XModifierKey::StoreState(guint32* state_store) const
{
  guint32 non_mask_bits = ~gdk_mod_mask_;
  guint32 toggle_bit = (toggle_ ? gdk_mod_mask_ : 0);

  *state_store = (*state_store & non_mask_bits) | toggle_bit;
  LOG(DEBUG) << "Storing state for " << gdk_mod_mask_ << " toggled? " << toggle_ <<
    " state store: " << *state_store << " non-mask bits: " << std::hex << non_mask_bits;
}

// Definition of a key press, release events pair.
typedef std::pair<GdkEvent*, GdkEvent*> KeyEventsPair;
enum KeyEventType { kKeyPress, kKeyRelease };
// This class handles generation of key press / release events.
// Events will be generated according to the given key to emulate
// and state of modifier keys.
class KeypressEventsHandler
{
public:
  KeypressEventsHandler(GdkDrawable* win_handle, guint32 modifiers_state);
  virtual ~KeypressEventsHandler();

  // Create a series of key release events that were left on at the end of
  // a sendKeys call.
  list<GdkEvent*> CreateModifierReleaseEvents();

  // Creates a series of key events according to the key to emulate
  // Cases:
  // 1. Null key: Reset modifiers state and return no events.
  // 2. lowercase letter: Create KeyPress, KeyRelease events.
  // 3. Uppercase letter: Creates Shift Down, KeyPress, KeyRelease
  //    and Shift Up events.
  // 4. Modifier: KeyPress event only, unless it was down
  // already - in which case, a KeyRelease
  list<GdkEvent*> CreateEventsForKey(wchar_t key_to_emulate);
  // Returns the time of the latest event.
  guint32 get_last_event_time();
  // Returns the state of modifier keys, to be stored between calls.
  guint32 getModifierKeysState();


private:
  // Create a keyboard event for a character or a non-modifier key
  // (arrow or tab keys, for example).
  GdkEvent* CreateKeyEvent(wchar_t key_to_emulate, KeyEventType ev_type);
  // Create a keyboard event for a modifier key - for example, when
  // shift is pressed.
  GdkEvent* CreateModifierKeyEvent(wchar_t key_to_emulate);
  // Returns true if the given character represents any of the modifier keys
  // the instance of this class knows about.
  bool IsModifierKey(wchar_t key);
  // Generates key down / up pair for a regular character.
  KeyEventsPair CreateKeyDownUpEvents(wchar_t key_to_emulate);

  // Creates a generic key event - used by the public methods
  // that generate events. Not used for modifier keys.
  GdkEvent* CreateGenericKeyEvent(wchar_t key_to_emulate, KeyEventType ev_type);

  // Similar to CreateGenericKeyEvent, but for modifier keys.
  GdkEvent* CreateGenericModifierKeyEvent(guint gdk_key, KeyEventType ev_type);
  // Creates an empty event.
  GdkEvent* CreateEmptyKeyEvent(KeyEventType ev_type);

  // Modifiers related.
  // Clears all of the modifiers
  void ClearModifiers();
  // Creates XModifierKey instances for a list of known, hard-coded
  // modifier keys.
  void InitModifiers();
  // Stores the state of all modifier keys into the static field.
  void StoreModifiersState();
  // Given a mask, add bits representing all of the relevant set modifiers
  // to it.
  void AddModifiersToMask(guint& mask_to_modifiy);
  // Returns true if a modifier, representing this gdk key, is set.
  bool IsModifierSet(guint gdk_key);
  // Called during handling of a modifier key, this method stores
  // the change of the appropriate modifier key (toggles it).
  void StoreModifierKeyState(guint gdk_mod_key);
  // Returns true if the Shift modifier is set.
  bool IsShiftSet();

  // Members.
  // Known modifiers and their states.
  list<XModifierKey> modifiers_;
  // The window handle to be used.
  GdkDrawable* win_handle_;
  // Time of the most recent event created.
  guint32 last_event_time_;
  // State of modifier keys - initialized from a global
  guint32 modifiers_state_;
};

// Sets the is_modifier field of the GdkEvent according to the supplied
// boolean.
static void SetIsModifierEvent(GdkEvent* p_ev, bool is_modifier)
{
  assert(p_ev->type == GDK_KEY_RELEASE || p_ev->type == GDK_KEY_PRESS);
  p_ev->key.is_modifier = (int) is_modifier;
}

KeypressEventsHandler::KeypressEventsHandler(GdkDrawable* win_handle, guint32 modifiers_state) :
  modifiers_(), win_handle_(win_handle), last_event_time_(TimeSinceBootMsec()),
  modifiers_state_(modifiers_state)
{
  InitModifiers();
}

// Will be called for the "Null" key.
void KeypressEventsHandler::ClearModifiers()
{
  for_each(modifiers_.begin(), modifiers_.end(),
           mem_fun_ref(&XModifierKey::ClearModifier));
}

void KeypressEventsHandler::InitModifiers()
{
  if (modifiers_.empty() == false) {
    modifiers_.clear();
  }

  modifiers_.push_back(XModifierKey(GDK_Shift_L, GDK_SHIFT_MASK, modifiers_state_));
  modifiers_.push_back(XModifierKey(GDK_Control_L, GDK_CONTROL_MASK, modifiers_state_));
  modifiers_.push_back(XModifierKey(GDK_Alt_L, GDK_MOD1_MASK, modifiers_state_));
}

void KeypressEventsHandler::StoreModifiersState()
{
  for_each(modifiers_.begin(), modifiers_.end(),
           bind2nd(mem_fun_ref(&XModifierKey::StoreState), &modifiers_state_));
  LOG(DEBUG) << "Stored modifiers: " << modifiers_state_;
}

bool KeypressEventsHandler::IsModifierKey(wchar_t key)
{
  bool is_modifier = false;
  guint gdk_key_sym = translate_code_to_gdk_symbol(key);
  for (list<XModifierKey>::iterator it = modifiers_.begin();
       it != modifiers_.end(); ++it) {
    is_modifier |= it->KeyMatches(gdk_key_sym);
  }

  return is_modifier;
}

bool KeypressEventsHandler::IsModifierSet(guint gdk_key)
{
  list<XModifierKey>::iterator it =
      find_if(modifiers_.begin(), modifiers_.end(),
              bind2nd(mem_fun_ref(&XModifierKey::KeyMatches), gdk_key));

  if (it == modifiers_.end()) {
    return false;
  }

  return it->get_toggle();
}

void KeypressEventsHandler::StoreModifierKeyState(guint gdk_mod_key)
{
  for_each(modifiers_.begin(), modifiers_.end(),
           bind2nd(mem_fun_ref(&XModifierKey::ToggleIfKeyMatches),
                   gdk_mod_key));
  StoreModifiersState();
}

void KeypressEventsHandler::AddModifiersToMask(guint& mask_to_modifiy)
{
  for (list<XModifierKey>::iterator it = modifiers_.begin();
       it != modifiers_.end(); ++it) {
    mask_to_modifiy|= it->GetAppropriateMask();
  }
}

bool modifier_is_shift(const XModifierKey& k)
{
  return (k.get_associated_key() == GDK_Shift_L);
}

bool KeypressEventsHandler::IsShiftSet()
{
  list<XModifierKey>::iterator it =
      find_if(modifiers_.begin(), modifiers_.end(), modifier_is_shift);
  assert(it != modifiers_.end());
  return it->get_toggle();
}

guint32 KeypressEventsHandler::get_last_event_time()
{
  return last_event_time_;
}

guint32 KeypressEventsHandler::getModifierKeysState()
{
  return modifiers_state_;
}


GdkEvent* KeypressEventsHandler::CreateEmptyKeyEvent(KeyEventType ev_type)
{
  GdkEventType gdk_ev = GDK_KEY_PRESS;
  if (ev_type == kKeyRelease) {
    gdk_ev = GDK_KEY_RELEASE;
  }
  GdkEvent* p_ev = gdk_event_new(gdk_ev);
  p_ev->key.window = GDK_WINDOW(g_object_ref(win_handle_));
  p_ev->key.send_event = 0; // NOT a synthesized event.
  p_ev->key.time = TimeSinceBootMsec();
  // Also update the latest event time
  last_event_time_ = p_ev->key.time;
  // Deprecated.
  p_ev->key.length = 0;
  p_ev->key.string = NULL;
  // Put a default key code for space. This will be fixed later
  // by callers, that will translate the given character to
  // its appropriate keycode.
  const guint16 kSpaceKeycode = 65;
  p_ev->key.hardware_keycode = kSpaceKeycode;
  // This flag will be set to true later, if we indeed create
  // a modifier key event.
  SetIsModifierEvent(p_ev, false);

  // This applies to regular characters, keys and modifiers.
  // This must be done before the special handling for modifier
  // keys, as it will change the internal state of the modifiers.
  AddModifiersToMask(p_ev->key.state);

  return p_ev;
}

static guint16 get_keycode_for_key(guint for_key)
{
  guint16 ret_kc;
  const char* display_name = gdk_display_get_name(gdk_display_get_default());
  Display* xdisplay = XOpenDisplay(display_name);
  assert(xdisplay != NULL);

  KeyCode kc = XKeysymToKeycode(xdisplay, for_key);
  LOG(DEBUG) << "Got keycode: " << (int) kc;
  XCloseDisplay(xdisplay);
  ret_kc = (int) kc;

  return ret_kc;
}

GdkEvent* KeypressEventsHandler::CreateGenericKeyEvent(wchar_t key_to_emulate,
                                                       KeyEventType ev_type)
{
  GdkEvent* p_ev = CreateEmptyKeyEvent(ev_type);

  guint translated_key = translate_code_to_gdk_symbol(key_to_emulate);
  // Common case - key is not a modifier or a special key (arrow, tab, etc)
  if (translated_key == GDK_VoidSymbol) {
    // Ordinary character.
    p_ev->key.keyval = gdk_unicode_to_keyval(key_to_emulate);
  } else {
    // Special key
    p_ev->key.keyval = translated_key;
  }

  p_ev->key.hardware_keycode = get_keycode_for_key(p_ev->key.keyval);

  if (IsShiftSet()) {
    p_ev->key.keyval = gdk_keyval_to_upper(p_ev->key.keyval);
  }

  return p_ev;
}

GdkEvent* KeypressEventsHandler::CreateGenericModifierKeyEvent(
    guint gdk_key, KeyEventType ev_type)
{
  GdkEvent* p_ev = CreateEmptyKeyEvent(ev_type);

  p_ev->key.keyval = gdk_key;
  p_ev->key.hardware_keycode = get_keycode_for_key(p_ev->key.keyval);

  SetIsModifierEvent(p_ev, true);

  return p_ev;
}
GdkEvent* KeypressEventsHandler::CreateKeyEvent(wchar_t key_to_emulate,
                                                KeyEventType ev_type)
{
    // Should only be called with non-modifier keys.
    assert(IsModifierKey(key_to_emulate) == false);
    return CreateGenericKeyEvent(key_to_emulate, ev_type);
}

KeyEventsPair KeypressEventsHandler::CreateKeyDownUpEvents(
    wchar_t key_to_emulate)
{
  GdkEvent* down = CreateKeyEvent(key_to_emulate, kKeyPress);
  GdkEvent* up = CreateKeyEvent(key_to_emulate, kKeyRelease);
  return std::make_pair(down, up);
}

GdkEvent* KeypressEventsHandler::CreateModifierKeyEvent(
    wchar_t key_to_emulate)
{
    guint translated_key = translate_code_to_gdk_symbol(key_to_emulate);
    assert(translated_key != GDK_VoidSymbol);
    // If the modifier is set - this is a release event, otherwise - 
    // a key press.
    KeyEventType ev_type = kKeyPress;
    if (IsModifierSet(translated_key)) {
      ev_type = kKeyRelease;
    }
    GdkEvent* ret_event =
        CreateGenericModifierKeyEvent(translated_key, ev_type);

    StoreModifierKeyState(translated_key);
    return ret_event;
}

list<GdkEvent*> KeypressEventsHandler::CreateModifierReleaseEvents()
{
  list<GdkEvent*> ret_list;
  for (list<XModifierKey>::iterator it = modifiers_.begin();
       it != modifiers_.end(); ++it) {
    if (it->get_toggle()) {
      GdkEvent* rel_event =
          CreateGenericModifierKeyEvent(it->get_associated_key(), kKeyRelease);
      ret_list.push_back(rel_event);
      it->ClearModifier();
    }
  }

  StoreModifiersState();

  return ret_list;
}

bool is_lowercase_symbol(wchar_t key_to_emulate)
{
  // Note that it is *only* allowed for keys that cannot be translated
  // this bears the assumption that keys defined in Keys.java do not
  // have a different "capitalized" representation.
  // This makes sense as the keys in Keys.java are non-alphanumeric
  // keys (arrows, tab, etc);
  //
  assert(translate_code_to_gdk_symbol(key_to_emulate) == GDK_VoidSymbol);

  string chars_req_shift = "!$^*()+{}:?|~@#%&_\"<>";

  bool shift_needed = (chars_req_shift.find(toascii(key_to_emulate)) !=
                       string::npos);
  // If the representation is different than the lowercase 
  // representation, this is not a lowercase character.
  if (shift_needed || (key_to_emulate != towlower(key_to_emulate))) {
    return false;
  }
  return true;
}

list<GdkEvent*> KeypressEventsHandler::CreateEventsForKey(
    wchar_t key_to_emulate)
{
 list<GdkEvent*> ret_list;
  // First case - is it the NULL symbol? If so, reset modifiers and exit.
  if (key_to_emulate == gNullKey) {
    LOG(DEBUG) << "Null key - clearing modifiers.";
    return CreateModifierReleaseEvents();
  }

  // Now: The key is either a modifier key or character key.
  // Common case - not a modifier key. Need two events - Key press and
  // key release.
  if (IsModifierKey(key_to_emulate) == false) {
    LOG(DEBUG) << "Key: " << key_to_emulate  << " is not a modifier.";

    guint translated_key = translate_code_to_gdk_symbol(key_to_emulate);
    // First - check to see if this is an lowercase letter or is a
    // non-alphanumeric key (which cannot be capitalized)
    if ((translated_key != GDK_VoidSymbol) ||
        (is_lowercase_symbol(key_to_emulate))) {
      LOG(DEBUG) << "Lowercase letter or non void gdk symbol.";
      // More common case - lowercase letter.
      // Create only two events.
      // Note that if the Shift modifier is set, this character will
      // be converted to uppercase by CreateKeyEvent method.
      KeyEventsPair ev = CreateKeyDownUpEvents(key_to_emulate);
      ret_list.push_back(ev.first);
      ret_list.push_back(ev.second);
    } else {
      // Uppercase letter/symbol: Fire up shift down event, this key and 
      // shift up event (unless the Shift modifier is already set)
      bool shift_was_set = IsShiftSet();
      LOG(DEBUG) << "Uppercase letter. Was shift set? " << shift_was_set;
      if (shift_was_set == false) {
        // push shift down event
        ret_list.push_front(
            CreateGenericModifierKeyEvent(GDK_Shift_L, kKeyPress));
        StoreModifierKeyState(GDK_Shift_L);
      }
      KeyEventsPair ev = CreateKeyDownUpEvents(key_to_emulate);
      // Push the events themselves.
      ret_list.push_back(ev.first);
      ret_list.push_back(ev.second);

      if (shift_was_set == false) {
        // push shift up event
        ret_list.push_back(
            CreateGenericModifierKeyEvent(GDK_Shift_L, kKeyRelease));
        // Turn OFF the shift modifier!
        StoreModifierKeyState(GDK_Shift_L);
      }
    }
  } else { // Modifier key.
    // When a modifier key is pressed, the state does not yet change to reflect
    // it (on the KeyPress event for the modifier key). When the modifier key is
    // released, the state indeed reflects that it was pressed.
    LOG(DEBUG) << "Key: " << key_to_emulate << " IS a modifier.";
    // generate only one keypress event, either press or release.
    GdkEvent* p_ev = CreateModifierKeyEvent(key_to_emulate);
    ret_list.push_back(p_ev);
  }

  return ret_list;
}

KeypressEventsHandler::~KeypressEventsHandler()
{
  modifiers_.clear();
}

static void submit_and_free_event(GdkEvent* p_key_event, int sleep_time_ms)
{
  gdk_event_put(p_key_event);
  gdk_event_free(p_key_event);
  sleep_for_ms(sleep_time_ms);
}

static void submit_and_free_events_list(list<GdkEvent*>& events_list,
                                        int sleep_time_ms)
{
    for_each(events_list.begin(), events_list.end(), print_key_event);

    for_each(events_list.begin(), events_list.end(),
             bind2nd(ptr_fun(submit_and_free_event), sleep_time_ms));

    events_list.clear();
}

// global variable declared here so it is not used beforehand.
guint32 gModifiersState = 0;

int getTimePerKey(int proposedTimePerKey)
{
  const int minTimePerKey = 10 /* ms */;
  if (proposedTimePerKey < minTimePerKey) {
    return minTimePerKey;
  }

  return proposedTimePerKey;
}

void updateLastEventTime(const guint32 lastEventTime) {
  if (gLatestEventTime < lastEventTime) {
    gLatestEventTime = lastEventTime;
  }
}

extern "C"
{
void sendKeys(WINDOW_HANDLE windowHandle, const wchar_t* value, int requestedTimePerKey)
{
  init_logging();
  int timePerKey = getTimePerKey(requestedTimePerKey);

  LOG(DEBUG) << "---------- starting sendKeys: " << windowHandle << " tpk: " <<
     timePerKey << "---------";
  GdkDrawable* hwnd = (GdkDrawable*) windowHandle;

  // The keyp_handler will remember the state of modifier keys and
  // will be used to generate the events themselves.
  KeypressEventsHandler keyp_handler(hwnd, gModifiersState);

  struct timespec sleep_time;
  sleep_time.tv_sec = timePerKey / 1000;
  sleep_time.tv_nsec = (timePerKey % 1000) * 1000000;
  LOG(DEBUG) << "Sleep time is " << sleep_time.tv_sec << " seconds and " <<
            sleep_time.tv_nsec << " nanoseconds.";

  int i = 0;
  while (value[i] != '\0') {
    list<GdkEvent*> events_for_key =
        keyp_handler.CreateEventsForKey(value[i]);

    submit_and_free_events_list(events_for_key, timePerKey);

    i++;
  }

  updateLastEventTime(keyp_handler.get_last_event_time());
  gModifiersState = keyp_handler.getModifierKeysState();

  LOG(DEBUG) << "---------- Ending sendKeys. Total keys: " << i
            << "  ----------";
}

void releaseModifierKeys(WINDOW_HANDLE windowHandle, int requestedTimePerKey)
{
  init_logging();
  int timePerKey = getTimePerKey(requestedTimePerKey);

  LOG(DEBUG) << "---------- starting releaseModifierKeys: " << windowHandle << " tpk: " <<
     timePerKey << "---------";
  GdkDrawable* hwnd = (GdkDrawable*) windowHandle;

  // The state of the modifier keys is stored - just calling release will work.
  KeypressEventsHandler keyp_handler(hwnd, gModifiersState);

  // Free the remaining modifiers that are still set.
  list<GdkEvent*> modifier_release_events =
      keyp_handler.CreateModifierReleaseEvents();
  int num_released = modifier_release_events.size();

  submit_and_free_events_list(modifier_release_events, timePerKey);

  updateLastEventTime(keyp_handler.get_last_event_time());
  gModifiersState = keyp_handler.getModifierKeysState();

  LOG(DEBUG) << "---------- Ending releaseModifierKeys. Released: " << num_released
    << "  ----------";
}

}
