// 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 <deque>
#include <string>
#include <vector>

#include "base/memory/scoped_ptr.h"
#include "chrome/browser/extensions/api/serial/serial_api.h"
#include "chrome/browser/extensions/api/serial/serial_connection.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extension_function.h"
#include "chrome/browser/extensions/extension_function_test_utils.h"
#include "chrome/browser/extensions/extension_test_message_listener.h"
#include "chrome/browser/ui/browser.h"
#include "content/public/browser/browser_thread.h"
#include "testing/gmock/include/gmock/gmock.h"

using testing::_;
using testing::Return;

using content::BrowserThread;

namespace serial = extensions::api::serial;

namespace {

class SerialApiTest : public ExtensionApiTest {
 public:
  SerialApiTest() {}
};

}  // namespace

namespace extensions {

class FakeSerialGetPortsFunction : public AsyncExtensionFunction {
 public:
  virtual bool RunImpl() OVERRIDE {
    base::ListValue* ports = new base::ListValue();
    ports->Append(Value::CreateStringValue("/dev/fakeserial"));
    ports->Append(Value::CreateStringValue("\\\\COM800\\"));
    SetResult(ports);
    SendResponse(true);
    return true;
  }
 protected:
  virtual ~FakeSerialGetPortsFunction() {}
};

class FakeEchoSerialConnection : public SerialConnection {
 public:
  explicit FakeEchoSerialConnection(
      const std::string& port,
      int bitrate,
      serial::DataBit databit,
      serial::ParityBit parity,
      serial::StopBit stopbit,
      const std::string& owner_extension_id)
      : SerialConnection(port, bitrate, databit, parity, stopbit,
                        owner_extension_id),
        opened_(true) {
    Flush();
    opened_ = false;
  }

  virtual ~FakeEchoSerialConnection() {
  }

  virtual bool Open() {
    DCHECK(!opened_);
    opened_ = true;
    return true;
  }

  virtual void Close() {
    DCHECK(opened_);
  }

  virtual void Flush() {
    DCHECK(opened_);
    buffer_.clear();
  }

  virtual int Read(scoped_refptr<net::IOBufferWithSize> io_buffer) {
    DCHECK(io_buffer->data());

    if (buffer_.empty()) {
      return 0;
    }
    char *data = io_buffer->data();
    int bytes_to_copy = io_buffer->size();
    while (bytes_to_copy-- && !buffer_.empty()) {
      *data++ = buffer_.front();
      buffer_.pop_front();
    }
    return io_buffer->size();
  }

  virtual int Write(scoped_refptr<net::IOBuffer> io_buffer, int byte_count) {
    DCHECK(io_buffer.get());
    DCHECK_GE(byte_count, 0);

    char *data = io_buffer->data();
    int count = byte_count;
    while (count--)
      buffer_.push_back(*data++);
    return byte_count;
  }

  MOCK_METHOD1(GetControlSignals, bool(ControlSignals &));
  MOCK_METHOD1(SetControlSignals, bool(const ControlSignals &));

 private:
  bool opened_;
  std::deque<char> buffer_;

  DISALLOW_COPY_AND_ASSIGN(FakeEchoSerialConnection);
};

class FakeSerialOpenFunction : public SerialOpenFunction {
 protected:
  virtual SerialConnection* CreateSerialConnection(
      const std::string& port,
      int bitrate,
      serial::DataBit databit,
      serial::ParityBit parity,
      serial::StopBit stopbit,
      const std::string& owner_extension_id) OVERRIDE {
    FakeEchoSerialConnection* serial_connection =
        new FakeEchoSerialConnection(port, bitrate, databit, parity, stopbit,
                                     owner_extension_id);
    EXPECT_CALL(*serial_connection, GetControlSignals(_)).
        Times(1).WillOnce(Return(true));
    EXPECT_CALL(*serial_connection, SetControlSignals(_)).
        Times(1).WillOnce(Return(true));
    return serial_connection;
  }
  virtual bool DoesPortExist(const std::string& port) OVERRIDE {
    return true;
  }

 protected:
  virtual ~FakeSerialOpenFunction() {}
};

}  // namespace extensions

ExtensionFunction* FakeSerialGetPortsFunctionFactory() {
  return new extensions::FakeSerialGetPortsFunction();
}

ExtensionFunction* FakeSerialOpenFunctionFactory() {
  return new extensions::FakeSerialOpenFunction();
}

// Disable SIMULATE_SERIAL_PORTS only if all the following are true:
//
// 1. You have an Arduino or compatible board attached to your machine and
// properly appearing as the first virtual serial port ("first" is very loosely
// defined as whichever port shows up in serial.getPorts). We've tested only
// the Atmega32u4 Breakout Board and Arduino Leonardo; note that both these
// boards are based on the Atmel ATmega32u4, rather than the more common
// Arduino '328p with either FTDI or '8/16u2 USB interfaces. TODO: test more
// widely.
//
// 2. Your user has permission to read/write the port. For example, this might
// mean that your user is in the "tty" or "uucp" group on Ubuntu flavors of
// Linux, or else that the port's path (e.g., /dev/ttyACM0) has global
// read/write permissions.
//
// 3. You have uploaded a program to the board that does a byte-for-byte echo
// on the virtual serial port at 57600 bps. An example is at
// chrome/test/data/extensions/api_test/serial/api/serial_arduino_test.ino.
//
#define SIMULATE_SERIAL_PORTS (1)
IN_PROC_BROWSER_TEST_F(SerialApiTest, SerialFakeHardware) {
  ResultCatcher catcher;
  catcher.RestrictToProfile(browser()->profile());

#if SIMULATE_SERIAL_PORTS
  ASSERT_TRUE(ExtensionFunctionDispatcher::OverrideFunction(
      "serial.getPorts",
      FakeSerialGetPortsFunctionFactory));
  ASSERT_TRUE(ExtensionFunctionDispatcher::OverrideFunction(
      "serial.open",
      FakeSerialOpenFunctionFactory));
#endif

  ASSERT_TRUE(RunExtensionTest("serial/api")) << message_;
}

IN_PROC_BROWSER_TEST_F(SerialApiTest, SerialRealHardware) {
  ResultCatcher catcher;
  catcher.RestrictToProfile(browser()->profile());

  ASSERT_TRUE(RunExtensionTest("serial/real_hardware")) << message_;
}
