// Copyright 2015 The Cobalt Authors. 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/memory/scoped_ptr.h"
#include "base/message_loop.h"
#include "base/rand_util.h"
#include "cobalt/base/tokens.h"
#include "cobalt/dom/keyboard_event.h"
#include "cobalt/dom/keycode.h"

namespace cobalt {
namespace input {

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];
}

base::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_ +
         base::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),
                               base::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,
  //                        base::TimeDelta::FromSeconds(1)));
  //   key_infos_.push_back(KeyInfo(keycode::kEscape,
  //                        base::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();

  dom::KeyboardEventInit event_init;
  event_init.set_key_code(key_code);

  keyboard_event_callback_.Run(base::Tokens::keydown(), event_init);
  keyboard_event_callback_.Run(base::Tokens::keyup(), event_init);

  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
