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