// Copyright 2015 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 "tools/battor_agent/battor_connection_impl.h"

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/memory/ptr_util.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "device/serial/buffer.h"
#include "device/serial/serial_io_handler.h"
#include "net/base/io_buffer.h"
#include "tools/battor_agent/serial_utils.h"

using base::StringPrintf;
using std::vector;

namespace battor {

namespace {

// The command line switch used to specify a file to which serial communication
// is logged.
const char kSerialLogPathSwitch[] = "battor-serial-log";

// Serial configuration parameters for the BattOr.
const uint32_t kBattOrBitrate = 2000000;
const device::serial::DataBits kBattOrDataBits =
    device::serial::DataBits::EIGHT;
const device::serial::ParityBit kBattOrParityBit =
    device::serial::ParityBit::NONE;
const device::serial::StopBits kBattOrStopBit = device::serial::StopBits::ONE;
const bool kBattOrCtsFlowControl = true;
const bool kBattOrHasCtsFlowControl = true;
// The maximum BattOr message is 50kB long.
const size_t kMaxMessageSizeBytes = 50000;

// Returns the maximum number of bytes that could be required to read a message
// of the specified type.
size_t GetMaxBytesForMessageType(BattOrMessageType type) {
  switch (type) {
    case BATTOR_MESSAGE_TYPE_CONTROL:
      return 2 * sizeof(BattOrControlMessage) + 3;
    case BATTOR_MESSAGE_TYPE_CONTROL_ACK:
      // The BattOr EEPROM is sent back with this type, even though it's
      // technically more of a response than an ack. We have to make sure that
      // we read enough bytes to accommodate this behavior.
      return 2 * sizeof(BattOrEEPROM) + 3;
    case BATTOR_MESSAGE_TYPE_SAMPLES:
      return 2 * kMaxMessageSizeBytes + 3;
    default:
      return 0;
  }
}

}  // namespace

BattOrConnectionImpl::BattOrConnectionImpl(
    const std::string& path,
    BattOrConnection::Listener* listener,
    scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner)
    : BattOrConnection(listener),
      path_(path),
      ui_thread_task_runner_(ui_thread_task_runner) {
  std::string serial_log_path =
      base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
          kSerialLogPathSwitch);
  if (!serial_log_path.empty()) {
    serial_log_.open(serial_log_path.c_str(),
                     std::fstream::out | std::fstream::trunc);
  }
}

BattOrConnectionImpl::~BattOrConnectionImpl() {}

void BattOrConnectionImpl::Open() {
  if (io_handler_) {
    // Opening new connection so flush serial data from old connection.
    Flush();
    OnOpened(true);
    return;
  }

  io_handler_ = CreateIoHandler();

  device::serial::ConnectionOptions options;
  options.bitrate = kBattOrBitrate;
  options.data_bits = kBattOrDataBits;
  options.parity_bit = kBattOrParityBit;
  options.stop_bits = kBattOrStopBit;
  options.cts_flow_control = kBattOrCtsFlowControl;
  options.has_cts_flow_control = kBattOrHasCtsFlowControl;

  LogSerial("Opening serial connection.");
  io_handler_->Open(path_, options,
                    base::Bind(&BattOrConnectionImpl::OnOpened, AsWeakPtr()));
}

void BattOrConnectionImpl::OnOpened(bool success) {
  LogSerial(StringPrintf("Serial connection open finished with success: %d.",
                         success));

  if (!success)
    Close();

  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::Bind(&Listener::OnConnectionOpened,
                            base::Unretained(listener_), success));
}

void BattOrConnectionImpl::Close() {
  LogSerial("Serial connection closed.");
  io_handler_ = nullptr;
}

void BattOrConnectionImpl::SendBytes(BattOrMessageType type,
                                     const void* buffer,
                                     size_t bytes_to_send) {
  const char* bytes = reinterpret_cast<const char*>(buffer);

  // Reserve a send buffer with enough extra bytes for the start, type, end, and
  // escape bytes.
  vector<char> data;
  data.reserve(2 * bytes_to_send + 3);

  data.push_back(BATTOR_CONTROL_BYTE_START);
  data.push_back(type);

  for (size_t i = 0; i < bytes_to_send; i++) {
    if (bytes[i] == BATTOR_CONTROL_BYTE_START ||
        bytes[i] == BATTOR_CONTROL_BYTE_END) {
      data.push_back(BATTOR_CONTROL_BYTE_ESCAPE);
    }

    data.push_back(bytes[i]);
  }

  data.push_back(BATTOR_CONTROL_BYTE_END);

  LogSerial(StringPrintf("Bytes sent: %s.", CharVectorToString(data).c_str()));

  pending_write_length_ = data.size();
  io_handler_->Write(base::MakeUnique<device::SendBuffer>(
      data, base::Bind(&BattOrConnectionImpl::OnBytesSent, AsWeakPtr())));
}

void BattOrConnectionImpl::ReadMessage(BattOrMessageType type) {
  LogSerial("Read requested.");

  pending_read_message_type_ = type;
  size_t message_max_bytes = GetMaxBytesForMessageType(type);

  LogSerial(
      "Before doing a serial read, checking to see if we already have a "
      "complete message in the 'already read' buffer.");

  BattOrMessageType parsed_type;
  std::unique_ptr<vector<char>> bytes(new vector<char>());
  bytes->reserve(message_max_bytes);
  ParseMessageError parse_message_error =
      ParseMessage(&parsed_type, bytes.get());
  if (parse_message_error == ParseMessageError::NONE) {
    LogSerial("Complete message found.");
    EndReadBytes(true, parsed_type, std::move(bytes));
    return;
  }

  if (parse_message_error != ParseMessageError::NOT_ENOUGH_BYTES) {
    LogSerial(StringPrintf(
        "Read failed because, before performing a serial read, the message in "
        "the 'already read' buffer had an irrecoverable error with code: %d.",
        parse_message_error));
    EndReadBytes(false, BATTOR_MESSAGE_TYPE_CONTROL, nullptr);
    return;
  }

  LogSerial("No complete message found in the 'already read' buffer.");
  BeginReadBytes(message_max_bytes - already_read_buffer_.size());
}

void BattOrConnectionImpl::CancelReadMessage() {
  LogSerial("Canceling read due to timeout.");
  io_handler_->CancelRead(device::serial::ReceiveError::TIMEOUT);
}

void BattOrConnectionImpl::Flush() {
  io_handler_->Flush();
  already_read_buffer_.clear();
}

scoped_refptr<device::SerialIoHandler> BattOrConnectionImpl::CreateIoHandler() {
  return device::SerialIoHandler::Create(ui_thread_task_runner_);
}

void BattOrConnectionImpl::BeginReadBytes(size_t max_bytes_to_read) {
  LogSerial(
      StringPrintf("Starting read of up to %zu bytes.", max_bytes_to_read));

  pending_read_buffer_ =
      make_scoped_refptr(new net::IOBuffer(max_bytes_to_read));

  auto on_receive_buffer_filled =
      base::Bind(&BattOrConnectionImpl::OnBytesRead, AsWeakPtr());

  io_handler_->Read(base::MakeUnique<device::ReceiveBuffer>(
      pending_read_buffer_, static_cast<uint32_t>(max_bytes_to_read),
      on_receive_buffer_filled));
}

void BattOrConnectionImpl::OnBytesRead(int bytes_read,
                                       device::serial::ReceiveError error) {
  if (error != device::serial::ReceiveError::NONE) {
    LogSerial(StringPrintf(
        "Read failed due to serial read failure with error code: %d.",
        static_cast<int>(error)));
    EndReadBytes(false, BATTOR_MESSAGE_TYPE_CONTROL, nullptr);
    return;
  }

  // NOTE: Zero bytes may have been read.

  if (pending_read_message_type_ == BATTOR_MESSAGE_TYPE_SAMPLES) {
    // If we're reading samples, don't log every byte that we receive. This
    // exacerbates a problem on Mac wherein we can't process sample frames
    // quickly enough to prevent the serial buffer from overflowing, causing us
    // to drop frames.
    LogSerial(StringPrintf("%d more bytes read.", bytes_read));
  } else {
    LogSerial(StringPrintf(
        "%d more bytes read: %s.", bytes_read,
        CharArrayToString(pending_read_buffer_->data(), bytes_read).c_str()));
  }

  already_read_buffer_.insert(already_read_buffer_.end(),
                              pending_read_buffer_->data(),
                              pending_read_buffer_->data() + bytes_read);

  BattOrMessageType type;
  size_t message_max_bytes =
      GetMaxBytesForMessageType(pending_read_message_type_);
  std::unique_ptr<vector<char>> bytes(new vector<char>());
  bytes->reserve(message_max_bytes);

  ParseMessageError parse_message_error = ParseMessage(&type, bytes.get());
  if (parse_message_error == ParseMessageError::NOT_ENOUGH_BYTES) {
    if (already_read_buffer_.size() >= message_max_bytes) {
      LogSerial(
          "Read failed due to no complete message after max read length.");
      EndReadBytes(false, BATTOR_MESSAGE_TYPE_CONTROL, nullptr);
      return;
    }

    LogSerial("(Message still incomplete: reading more bytes.)");
    BeginReadBytes(message_max_bytes - already_read_buffer_.size());
    return;
  }

  if (parse_message_error != ParseMessageError::NONE) {
    LogSerial(StringPrintf(
        "Read failed due to the message containing an irrecoverable error: %d.",
        parse_message_error));
    EndReadBytes(false, BATTOR_MESSAGE_TYPE_CONTROL, nullptr);
    return;
  }

  if (type != pending_read_message_type_) {
    LogSerial("Read failed due to receiving a message of the wrong type.");
    EndReadBytes(false, BATTOR_MESSAGE_TYPE_CONTROL, nullptr);
    return;
  }

  EndReadBytes(true, type, std::move(bytes));
}

void BattOrConnectionImpl::EndReadBytes(bool success,
                                        BattOrMessageType type,
                                        std::unique_ptr<vector<char>> bytes) {
  LogSerial(StringPrintf("Read finished with success: %d.", success));

  pending_read_buffer_ = nullptr;
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE,
      base::Bind(&Listener::OnMessageRead, base::Unretained(listener_), success,
                 type, base::Passed(std::move(bytes))));
}

BattOrConnectionImpl::ParseMessageError BattOrConnectionImpl::ParseMessage(
    BattOrMessageType* type,
    vector<char>* bytes) {
  if (already_read_buffer_.size() <= 3)
    return ParseMessageError::NOT_ENOUGH_BYTES;

  // The first byte is the start byte.
  if (already_read_buffer_[0] != BATTOR_CONTROL_BYTE_START)
    return ParseMessageError::MISSING_START_BYTE;

  // The second byte specifies the message type.
  *type = static_cast<BattOrMessageType>(already_read_buffer_[1]);

  if (*type < static_cast<uint8_t>(BATTOR_MESSAGE_TYPE_CONTROL) ||
      *type > static_cast<uint8_t>(BATTOR_MESSAGE_TYPE_PRINT))
    return ParseMessageError::INVALID_MESSAGE_TYPE;

  // After that comes the message bytes.
  bool escape_next_byte = false;
  for (size_t i = 2; i < already_read_buffer_.size(); i++) {
    char next_byte = already_read_buffer_[i];

    if (escape_next_byte) {
      bytes->push_back(next_byte);
      escape_next_byte = false;
      continue;
    }

    switch (next_byte) {
      case BATTOR_CONTROL_BYTE_START:
        // Two start bytes in a message is invalid.
        return ParseMessageError::TOO_MANY_START_BYTES;

      case BATTOR_CONTROL_BYTE_END:
        already_read_buffer_.erase(already_read_buffer_.begin(),
                                   already_read_buffer_.begin() + i + 1);
        return ParseMessageError::NONE;

      case BATTOR_CONTROL_BYTE_ESCAPE:
        escape_next_byte = true;
        continue;

      default:
        bytes->push_back(next_byte);
    }
  }

  // If we made it to the end of the read buffer and no end byte was seen, then
  // we don't have a complete message.
  return ParseMessageError::NOT_ENOUGH_BYTES;
}

void BattOrConnectionImpl::OnBytesSent(int bytes_sent,
                                       device::serial::SendError error) {
  bool success = (error == device::serial::SendError::NONE) &&
                 (pending_write_length_ == static_cast<size_t>(bytes_sent));
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE,
      base::Bind(&Listener::OnBytesSent, base::Unretained(listener_), success));
}

void BattOrConnectionImpl::LogSerial(const std::string& str) {
  serial_log_ << base::Time::Now() << ": " << str << std::endl << std::endl;
}

}  // namespace battor
