// Copyright (c) 2012 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 "remoting/client/key_event_mapper.h"

#include "remoting/proto/event.pb.h"

namespace remoting {

KeyEventMapper::KeyEventMapper() {
}

KeyEventMapper::KeyEventMapper(InputStub* stub) : protocol::InputFilter(stub) {
}

KeyEventMapper::~KeyEventMapper() {
}

void KeyEventMapper::SetTrapCallback(KeyTrapCallback callback) {
  trap_callback = callback;
}

void KeyEventMapper::TrapKey(uint32_t usb_keycode, bool trap_key) {
  if (trap_key) {
    trapped_keys.insert(usb_keycode);
  } else {
    trapped_keys.erase(usb_keycode);
  }
}

void KeyEventMapper::RemapKey(uint32_t in_usb_keycode,
                              uint32_t out_usb_keycode) {
  if (in_usb_keycode == out_usb_keycode) {
    mapped_keys.erase(in_usb_keycode);
  } else {
    mapped_keys[in_usb_keycode] = out_usb_keycode;
  }
}

void KeyEventMapper::InjectKeyEvent(const protocol::KeyEvent& event) {
  if (event.has_usb_keycode()) {
    // Deliver trapped keys to the callback, not the next stub.
    if (!trap_callback.is_null() && event.has_pressed() &&
        (trapped_keys.find(event.usb_keycode()) != trapped_keys.end())) {
      trap_callback.Run(event);
      return;
    }

    // Re-map mapped keys to the new value before passing them on.
    std::map<uint32_t, uint32_t>::iterator mapped =
        mapped_keys.find(event.usb_keycode());
    if (mapped != mapped_keys.end()) {
      protocol::KeyEvent new_event(event);
      new_event.set_usb_keycode(mapped->second);
      InputFilter::InjectKeyEvent(new_event);
      return;
    }
  }

  InputFilter::InjectKeyEvent(event);
}

}  // namespace remoting
