// 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/input/input_device_manager_fuzzer.h"

#include "base/basictypes.h"
#include "base/bind.h"
#include "base/message_loop.h"
#include "base/rand_util.h"
#include "cobalt/base/tokens.h"
#include "cobalt/dom/keycode.h"

namespace cobalt {
namespace input {

using base::TimeDelta;
using dom::KeyboardEvent;

namespace {

// Initialize the set of key events we are able to produce.
const int kKeyCodes[] = {dom::keycode::kUp,     dom::keycode::kDown,
                         dom::keycode::kLeft,   dom::keycode::kRight,
                         dom::keycode::kReturn, dom::keycode::kEscape};

}  // namespace

InputDeviceManagerFuzzer::KeyInfo::KeyInfo(const int* key_codes,
                                           size_t num_of_key_codes,
                                           base::TimeDelta delay) {
  DCHECK_GT(num_of_key_codes, 0);
  key_codes_.assign(key_codes, key_codes + num_of_key_codes);
  minimum_delay_ = delay;
  maximum_delay_ = delay;
}

InputDeviceManagerFuzzer::KeyInfo::KeyInfo(const int* key_codes,
                                           size_t num_of_key_codes,
                                           base::TimeDelta minimum_delay,
                                           base::TimeDelta maximum_delay) {
  DCHECK_GT(num_of_key_codes, 0);
  DCHECK(minimum_delay <= maximum_delay);
  key_codes_.assign(key_codes, key_codes + num_of_key_codes);
  minimum_delay_ = minimum_delay;
  maximum_delay_ = maximum_delay;
}

InputDeviceManagerFuzzer::KeyInfo::KeyInfo(int key_code,
                                           base::TimeDelta delay) {
  key_codes_.push_back(key_code);
  minimum_delay_ = delay;
  maximum_delay_ = delay;
}

InputDeviceManagerFuzzer::KeyInfo::KeyInfo(int key_code,
                                           base::TimeDelta minimum_delay,
                                           base::TimeDelta maximum_delay) {
  DCHECK(minimum_delay <= maximum_delay);
  key_codes_.push_back(key_code);
  minimum_delay_ = minimum_delay;
  maximum_delay_ = maximum_delay;
}

int InputDeviceManagerFuzzer::KeyInfo::GetRandomKeyCode() const {
  int index = static_cast<int>(base::RandGenerator(key_codes_.size()));
  return key_codes_[index];
}

TimeDelta InputDeviceManagerFuzzer::KeyInfo::GetRandomDelay() const {
  if (minimum_delay_ == maximum_delay_) {
    return minimum_delay_;
  }
  int64 diff_in_microseconds =
      (maximum_delay_ - minimum_delay_).InMicroseconds();
  diff_in_microseconds = static_cast<int64>(
      base::RandGenerator(static_cast<uint64>(diff_in_microseconds)));
  return minimum_delay_ + TimeDelta::FromMicroseconds(diff_in_microseconds);
}

InputDeviceManagerFuzzer::InputDeviceManagerFuzzer(
    KeyboardEventCallback keyboard_event_callback)
    : keyboard_event_callback_(keyboard_event_callback),
      next_key_index_(0),
      thread_("InputDeviceManagerFuzzer") {
  key_infos_.push_back(KeyInfo(kKeyCodes, arraysize(kKeyCodes),
                               TimeDelta::FromMilliseconds(400)));
  // Modify the key_infos_ to use different input patterns.  For example, the
  // following pattern can be used to test play and stop of a video repeatedly.
  //   key_infos_.push_back(KeyInfo(keycode::kReturn,
  //                        TimeDelta::FromSeconds(1)));
  //   key_infos_.push_back(KeyInfo(keycode::kEscape,
  //                        TimeDelta::FromSeconds(1)));

  // Schedule task to send the first key event.  Add an explicit delay to avoid
  // possible conflicts with debug console.
  thread_.Start();
  thread_.message_loop()->PostDelayedTask(
      FROM_HERE, base::Bind(&InputDeviceManagerFuzzer::OnNextEvent,
                            base::Unretained(this)),
      base::TimeDelta::FromSeconds(5));
}

void InputDeviceManagerFuzzer::OnNextEvent() {
  DCHECK_LT(next_key_index_, key_infos_.size());
  int key_code = key_infos_[next_key_index_].GetRandomKeyCode();

  KeyboardEvent::Data key_down_event(
      KeyboardEvent::kTypeKeyDown, KeyboardEvent::kDomKeyLocationStandard,
      KeyboardEvent::kNoModifier, key_code, 0, false);

  keyboard_event_callback_.Run(key_down_event);

  KeyboardEvent::Data key_up_event(
      KeyboardEvent::kTypeKeyUp, KeyboardEvent::kDomKeyLocationStandard,
      KeyboardEvent::kNoModifier, key_code, 0, false);

  keyboard_event_callback_.Run(key_up_event);

  MessageLoop::current()->PostDelayedTask(
      FROM_HERE, base::Bind(&InputDeviceManagerFuzzer::OnNextEvent,
                            base::Unretained(this)),
      key_infos_[next_key_index_].GetRandomDelay());
  next_key_index_ = (next_key_index_ + 1) % key_infos_.size();
}

}  // namespace input
}  // namespace cobalt
