// 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/base/token.h"
#include "cobalt/base/tokens.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(base::Tokens::keydown(), key_code, char_code, location);
  }

  void AddKeyPressEvent(int key_code, int char_code, KeyLocationCode location) {
    AddKeyEvent(base::Tokens::keypress(), key_code, char_code, location);
  }

  void AddKeyUpEvent(int key_code, int char_code, KeyLocationCode location) {
    AddKeyEvent(base::Tokens::keyup(), key_code, char_code, location);
  }

  void AddKeyEvent(base::Token type, int key_code, int char_code,
                   KeyLocationCode location) {
    dom::KeyboardEventInit event;
    event.set_location(location);
    event.set_shift_key(shift_pressed_);
    event.set_ctrl_key(ctrl_pressed_);
    event.set_alt_key(alt_pressed_);
    event.set_key_code(key_code);
    event.set_char_code(char_code);
    event.set_repeat(false);
    event_vector_->push_back(std::make_pair(type, event));
  }

  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
