/*
 * 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
