/*
 * Copyright 2015 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 "cobalt/webdriver/keyboard.h"

#include <limits>

#include "base/i18n/char_iterator.h"
#include "cobalt/dom/keycode.h"

using cobalt::dom::KeyboardEvent;

namespace cobalt {
namespace webdriver {
namespace {

typedef KeyboardEvent::KeyLocationCode KeyLocationCode;

// The following utf-8 code points could be provided as "keys" sent to
// WebDriver, and should be mapped to the corresponding keyboard code.
enum SpecialKey {
  kFirstSpecialKey = 0xE000,
  kSpecialKey_Null = kFirstSpecialKey,
  kSpecialKey_Cancel,
  kSpecialKey_Help,
  kSpecialKey_Backspace,
  kSpecialKey_Tab,
  kSpecialKey_Clear,
  kSpecialKey_Return,
  kSpecialKey_Enter,
  kSpecialKey_Shift,
  kSpecialKey_Ctrl,
  kSpecialKey_Alt,
  kSpecialKey_Pause,
  kSpecialKey_Escape,
  kSpecialKey_Space,
  kSpecialKey_Pageup,
  kSpecialKey_Pagedown,
  kSpecialKey_End,
  kSpecialKey_Home,
  kSpecialKey_LeftArrow,
  kSpecialKey_UpArrow,
  kSpecialKey_RightArrow,
  kSpecialKey_DownArrow,
  kSpecialKey_Insert,
  kSpecialKey_Delete,
  kSpecialKey_Semicolon,
  kSpecialKey_Equals,
  kSpecialKey_Numpad0,
  kSpecialKey_Numpad1,
  kSpecialKey_Numpad2,
  kSpecialKey_Numpad3,
  kSpecialKey_Numpad4,
  kSpecialKey_Numpad5,
  kSpecialKey_Numpad6,
  kSpecialKey_Numpad7,
  kSpecialKey_Numpad8,
  kSpecialKey_Numpad9,
  kSpecialKey_Multiply,
  kSpecialKey_Add,
  kSpecialKey_Separator,
  kSpecialKey_Subtract,
  kSpecialKey_Decimal,
  kSpecialKey_Divide,  // = 0xE029
  // 0xE02A to 0xE030 are not mapped to anything.
  kSpecialKey_F1 = 0xE031,  //
  kSpecialKey_F2,
  kSpecialKey_F3,
  kSpecialKey_F4,
  kSpecialKey_F5,
  kSpecialKey_F6,
  kSpecialKey_F7,
  kSpecialKey_F8,
  kSpecialKey_F9,
  kSpecialKey_F10,
  kSpecialKey_F11,
  kSpecialKey_F12,
  kSpecialKey_Meta,
  kLastSpecialKey = kSpecialKey_Meta
};
// Assert the expected values.
COMPILE_ASSERT(kSpecialKey_Divide == 0xE029, MissingAnEnum);
COMPILE_ASSERT(kLastSpecialKey == 0xE03D, MissingAnEnum);

// Mapping from a special keycode to virtual keycode. Subtract kFirstSpecialKey
// from the integer value of the WebDriver keycode and index into this table.
const int32 special_keycode_mapping[] = {
    dom::keycode::kUnknown,    // kSpecialKey_NULL
    dom::keycode::kCancel,     // kSpecialKey_Cancel,
    dom::keycode::kHelp,       // kSpecialKey_Help
    dom::keycode::kBack,       // kSpecialKey_Backspace,
    dom::keycode::kTab,        // kSpecialKey_Tab
    dom::keycode::kClear,      // kSpecialKey_Clear
    dom::keycode::kReturn,     // kSpecialKey_Return
    dom::keycode::kReturn,     // kSpecialKey_Enter (on numeric keypad)
    dom::keycode::kShift,      // kSpecialKey_Shift
    dom::keycode::kControl,    // kSpecialKey_Control
    dom::keycode::kMenu,       // kSpecialKey_Alt
    dom::keycode::kPause,      // kSpecialKey_Pause
    dom::keycode::kEscape,     // kSpecialKey_Escape
    dom::keycode::kSpace,      // kSpecialKey_Space
    dom::keycode::kPrior,      // kSpecialKey_Pageup,
    dom::keycode::kNext,       // kSpecialKey_Pagedown,
    dom::keycode::kEnd,        // kSpecialKey_End
    dom::keycode::kHome,       // kSpecialKey_Home
    dom::keycode::kLeft,       // kSpecialKey_LeftArrow,
    dom::keycode::kUp,         // kSpecialKey_UpArrow,
    dom::keycode::kRight,      // kSpecialKey_RightArrow,
    dom::keycode::kDown,       // kSpecialKey_DownArrow,
    dom::keycode::kInsert,     // kSpecialKey_Insert
    dom::keycode::kDelete,     // kSpecialKey_Delete
    dom::keycode::kOem1,       // kSpecialKey_Semicolon,
    dom::keycode::kOemPlus,    // kSpecialKey_Equals (on numeric keypad)
    dom::keycode::kNumpad0,    // kSpecialKey_Numpad0
    dom::keycode::kNumpad1,    // kSpecialKey_Numpad1
    dom::keycode::kNumpad2,    // kSpecialKey_Numpad2
    dom::keycode::kNumpad3,    // kSpecialKey_Numpad3
    dom::keycode::kNumpad4,    // kSpecialKey_Numpad4
    dom::keycode::kNumpad5,    // kSpecialKey_Numpad5
    dom::keycode::kNumpad6,    // kSpecialKey_Numpad6
    dom::keycode::kNumpad7,    // kSpecialKey_Numpad7
    dom::keycode::kNumpad8,    // kSpecialKey_Numpad8
    dom::keycode::kNumpad9,    // kSpecialKey_Numpad9
    dom::keycode::kMultiply,   // kSpecialKey_Multiply,
    dom::keycode::kAdd,        // kSpecialKey_Add
    dom::keycode::kSeparator,  // kSpecialKey_Separator
    dom::keycode::kSubtract,   // kSpecialKey_Subtract
    dom::keycode::kDecimal,    // kSpecialKey_Decimal
    dom::keycode::kDivide,     // kSpecialKey_Divide = 0xE029
    dom::keycode::kUnknown,    // 0xE02A
    dom::keycode::kUnknown,    // 0xE02B
    dom::keycode::kUnknown,    // 0xE02C
    dom::keycode::kUnknown,    // 0xE02D
    dom::keycode::kUnknown,    // 0xE02E
    dom::keycode::kUnknown,    // 0xE02F
    dom::keycode::kUnknown,    // 0xE030
    dom::keycode::kF1,         // kSpecialKey_F1 = 0xE031
    dom::keycode::kF2,         // kSpecialKey_F2
    dom::keycode::kF3,         // kSpecialKey_F3
    dom::keycode::kF4,         // kSpecialKey_F4
    dom::keycode::kF5,         // kSpecialKey_F5
    dom::keycode::kF6,         // kSpecialKey_F6
    dom::keycode::kF7,         // kSpecialKey_F7
    dom::keycode::kF8,         // kSpecialKey_F8
    dom::keycode::kF9,         // kSpecialKey_F9
    dom::keycode::kF10,        // kSpecialKey_F10
    dom::keycode::kF11,        // kSpecialKey_F11
    dom::keycode::kF12,        // kSpecialKey_F12
    dom::keycode::kLwin,       // kSpecialKey_Meta
};

// Check that the mapping is the expected size.
const int kLargestMappingIndex = kLastSpecialKey - kFirstSpecialKey;
COMPILE_ASSERT(arraysize(special_keycode_mapping) == kLargestMappingIndex + 1,
               IncorrectMappingTable);

// Translate a utf8 character to a keycode. Characters that would require the
// shift key to be pressed are lower-cased or translated to their corresponding
// non-shifted special character.
// This is based on a standard US keyboard.
int CharacterToKeyCode(char character) {
  if (character >= '0' && character <= '9') {
    return character;
  }
  if (character >= 'a' && character <= 'z') {
    return character - 32;
  }
  if (character >= 'A' && character <= 'Z') {
    return character;
  }

  switch (character) {
    case ' ':
      return dom::keycode::kSpace;
    case ')':
      return dom::keycode::k0;
    case '!':
      return dom::keycode::k1;
    case '@':
      return dom::keycode::k2;
    case '#':
      return dom::keycode::k3;
    case '$':
      return dom::keycode::k4;
    case '%':
      return dom::keycode::k5;
    case '^':
      return dom::keycode::k6;
    case '&':
      return dom::keycode::k7;
    case '*':
      return dom::keycode::k8;
    case '(':
      return dom::keycode::k9;

    case ':':
    case ';':
      return dom::keycode::kOem1;
    case '+':
    case '=':
      return dom::keycode::kOemPlus;
    case '<':
    case ',':
      return dom::keycode::kOemComma;
    case '_':
    case '-':
      return dom::keycode::kOemMinus;
    case '>':
    case '.':
      return dom::keycode::kOemPeriod;
    case '?':
    case '/':
      return dom::keycode::kOem2;
    case '~':
    case '`':
      return dom::keycode::kOem3;
    case '{':
    case '[':
      return dom::keycode::kOem4;
    case '|':
    case '\\':
      return dom::keycode::kOem5;
    case '}':
    case ']':
      return dom::keycode::kOem6;
    case '"':
    case '\'':
      return dom::keycode::kOem7;
  }
  NOTREACHED();
  return 0;
}

// Returns true iff this utf8 codepoint corresponds to a WebDriver special key.
bool IsSpecialKey(int webdriver_key) {
  return webdriver_key >= kFirstSpecialKey && webdriver_key < kLastSpecialKey;
}

bool IsModifierKey(int webdriver_key) {
  return webdriver_key == kSpecialKey_Alt ||
         webdriver_key == kSpecialKey_Shift ||
         webdriver_key == kSpecialKey_Ctrl;
}

// Returns true if typing the utf8 character on a standard US keyboard would
// require the shift modifier to be pressed.
bool CharacterRequiresShift(char character) {
  DCHECK_NE(0, character);
  const char kSpecialsRequiringShift[] = ")!@#$%%^&*(:+<_>?~{|}\"}";
  if (character >= 'A' && character <= 'Z') {
    return true;
  }
  return (strchr(kSpecialsRequiringShift, character) != NULL);
}

// Returns the keycode that corresponds to this WebDriver special key.
int32 GetSpecialKeycode(int32 webdriver_key) {
  DCHECK(IsSpecialKey(webdriver_key));
  int index = webdriver_key - kFirstSpecialKey;
  DCHECK_GE(index, 0);
  DCHECK_LT(index, arraysize(special_keycode_mapping));
  return special_keycode_mapping[index];
}

// Returns the location code for the key.
KeyLocationCode GetSpecialKeyLocation(int32 webdriver_key) {
  DCHECK(IsSpecialKey(webdriver_key));
  if ((webdriver_key >= kSpecialKey_Equals &&
       webdriver_key <= kSpecialKey_Divide) ||
      webdriver_key == kSpecialKey_Enter ||
      webdriver_key == kSpecialKey_Equals) {
    return KeyboardEvent::kDomKeyLocationNumpad;
  }
  if (webdriver_key == kSpecialKey_Shift || webdriver_key == kSpecialKey_Ctrl ||
      webdriver_key == kSpecialKey_Alt || webdriver_key == kSpecialKey_Meta) {
    // Choose all of these are the left ones. WebDriver doesn't distinguish
    // between left and right modifiers.
    return KeyboardEvent::kDomKeyLocationLeft;
  }
  // Other keys do not have a special location.
  return KeyboardEvent::kDomKeyLocationStandard;
}

class KeyTranslator {
 public:
  explicit KeyTranslator(Keyboard::KeyboardEventVector* event_vector)
      : shift_pressed_(false),
        ctrl_pressed_(false),
        alt_pressed_(false),
        event_vector_(event_vector) {}

  // Runs the sendKeys() algorithm to translate utf8 code points into key
  // press events.
  // https://www.w3.org/TR/webdriver/#sendkeys
  void Translate(const std::string& utf8_keys) {
    base::i18n::UTF8CharIterator utf8_iterator(&utf8_keys);
    while (!utf8_iterator.end()) {
      int32 webdriver_key = utf8_iterator.get();
      utf8_iterator.Advance();
      if (webdriver_key == kSpecialKey_Null) {
        // If it's a NULL key, release the modifiers.
        ReleaseModifiers();
        DCHECK(!shift_pressed_);
        DCHECK(!alt_pressed_);
        DCHECK(!ctrl_pressed_);
      } else if (IsModifierKey(webdriver_key)) {
        // Else if it's a modifier, toggle the modifier state.
        ToggleModifier(webdriver_key);
      } else if (IsSpecialKey(webdriver_key)) {
        // Else if it's a WebDriver special key, translate to key_code and
        // send key events.
        int32 key_code = GetSpecialKeycode(webdriver_key);
        int32 char_code = 0;
        KeyLocationCode location = GetSpecialKeyLocation(webdriver_key);
        AddKeyDownEvent(key_code, char_code, location);
        AddKeyUpEvent(key_code, char_code, location);
      } else {
        DCHECK_GE(webdriver_key, 0);
        DCHECK_LT(webdriver_key, std::numeric_limits<char>::max());
        const char character = static_cast<char>(webdriver_key);
        int key_code = CharacterToKeyCode(character);
        KeyLocationCode location = KeyboardEvent::kDomKeyLocationStandard;
        if (CharacterRequiresShift(character)) {
          // Handle Upper-case characters. Press and release Shift if it's not
          // being held already.
          bool shift_was_pressed = shift_pressed_;
          if (!shift_was_pressed) {
            ToggleModifier(kSpecialKey_Shift);
          }
          int32 char_code = KeyboardEvent::KeyCodeToCharCodeWithShift(key_code);
          DCHECK_EQ(char_code, character);

          AddKeyDownEvent(key_code, char_code, location);
          AddKeyPressEvent(key_code, char_code, location);
          AddKeyUpEvent(key_code, char_code, location);

          if (!shift_was_pressed) {
            ToggleModifier(kSpecialKey_Shift);
          }
        } else {
          // Handle lower-case characters. If shift is pressed, convert the
          // character to uppercase.
          int32 char_code = KeyboardEvent::KeyCodeToCharCodeNoShift(key_code);
          DCHECK_EQ(char_code, character);
          if (shift_pressed_) {
            char_code = KeyboardEvent::KeyCodeToCharCodeWithShift(key_code);
          }
          AddKeyDownEvent(key_code, char_code, location);
          AddKeyPressEvent(key_code, char_code, location);
          AddKeyUpEvent(key_code, char_code, location);
        }
      }
    }
  }

  void ReleaseModifiers() {
    if (alt_pressed_) {
      ToggleModifier(kSpecialKey_Alt);
    }
    if (ctrl_pressed_) {
      ToggleModifier(kSpecialKey_Ctrl);
    }
    if (shift_pressed_) {
      ToggleModifier(kSpecialKey_Shift);
    }
  }

 private:
  void ToggleModifier(int webdriver_key) {
    DCHECK(IsModifierKey(webdriver_key));
    bool do_keyup = false;
    if (webdriver_key == kSpecialKey_Alt) {
      do_keyup = alt_pressed_;
      alt_pressed_ = !alt_pressed_;
    } else if (webdriver_key == kSpecialKey_Shift) {
      do_keyup = shift_pressed_;
      shift_pressed_ = !shift_pressed_;
    } else if (webdriver_key == kSpecialKey_Ctrl) {
      do_keyup = ctrl_pressed_;
      ctrl_pressed_ = !ctrl_pressed_;
    } else {
      NOTREACHED();
    }
    DCHECK(IsSpecialKey(webdriver_key));
    int32 char_code = 0;
    int32 key_code = GetSpecialKeycode(webdriver_key);
    KeyLocationCode location = GetSpecialKeyLocation(webdriver_key);
    if (do_keyup) {
      AddKeyUpEvent(key_code, char_code, location);
    } else {
      AddKeyDownEvent(key_code, char_code, location);
    }
  }

  void AddKeyDownEvent(int key_code, int char_code, KeyLocationCode location) {
    AddKeyEvent(KeyboardEvent::kTypeKeyDown, key_code, char_code, location);
  }

  void AddKeyPressEvent(int key_code, int char_code, KeyLocationCode location) {
    AddKeyEvent(KeyboardEvent::kTypeKeyPress, key_code, char_code, location);
  }

  void AddKeyUpEvent(int key_code, int char_code, KeyLocationCode location) {
    AddKeyEvent(KeyboardEvent::kTypeKeyUp, key_code, char_code, location);
  }

  void AddKeyEvent(KeyboardEvent::Type type, int key_code, int char_code,
                   KeyLocationCode location) {
    const bool kIsRepeat = false;
    uint32 modifiers = GetModifierStateBitfield();
    event_vector_->push_back(dom::KeyboardEvent::Data(
        type, location, modifiers, key_code, char_code, kIsRepeat));
  }

  uint32 GetModifierStateBitfield() const {
    uint32 modifier_state = 0;
    if (shift_pressed_) {
      modifier_state |= KeyboardEvent::kShiftKey;
    }
    if (ctrl_pressed_) {
      modifier_state |= KeyboardEvent::kCtrlKey;
    }
    if (alt_pressed_) {
      modifier_state |= KeyboardEvent::kAltKey;
    }
    return modifier_state;
  }

  bool shift_pressed_;
  bool ctrl_pressed_;
  bool alt_pressed_;
  Keyboard::KeyboardEventVector* event_vector_;
};

}  // namespace

void Keyboard::TranslateToKeyEvents(const std::string& utf8_keys,
                                    TerminationBehaviour termination_behaviour,
                                    KeyboardEventVector* out_events) {
  KeyTranslator translator(out_events);
  translator.Translate(utf8_keys);
  if (termination_behaviour == kReleaseModifiers) {
    translator.ReleaseModifiers();
  }
}

}  // namespace webdriver
}  // namespace cobalt
