// 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 "apps/moterm/moterm_driver.h"

#include <algorithm>
#include <limits>

#include "base/logging.h"
#include "mojo/services/files/public/interfaces/ioctl.mojom.h"
#include "mojo/services/files/public/interfaces/ioctl_terminal.mojom.h"

// Character constants:
const uint8_t kEOT = 4;
const uint8_t kNL = 10;
const uint8_t kCR = 13;
const uint8_t kDEL = 127;

// Short forms for various counts/indices used for the get/set settings ioctls.
const size_t kBaseFieldCount = mojo::files::kIoctlTerminalTermiosBaseFieldCount;
const size_t kTotalFieldCount =
    kBaseFieldCount + mojo::files::kIoctlTerminalTermiosCtrlCharCount;
const size_t kIFlagIdx = mojo::files::kIoctlTerminalTermiosIFlagIndex;
const size_t kOFlagIdx = mojo::files::kIoctlTerminalTermiosOFlagIndex;
const size_t kLFlagIdx = mojo::files::kIoctlTerminalTermiosLFlagIndex;
const size_t kVEraseIdx = mojo::files::kIoctlTerminalTermiosCtrlCharVERASEIndex;
const size_t kVEOFIdx = mojo::files::kIoctlTerminalTermiosCtrlCharVERASEIndex;

MotermDriver::PendingRead::PendingRead(uint32_t num_bytes,
                                       const ReadCallback& callback)
    : num_bytes(num_bytes), callback(callback) {
}

MotermDriver::PendingRead::~PendingRead() {
}

// static
base::WeakPtr<MotermDriver> MotermDriver::Create(
    Client* client,
    mojo::InterfaceRequest<mojo::files::File> request) {
  return (new MotermDriver(client, request.Pass()))->weak_factory_.GetWeakPtr();
}

void MotermDriver::Detach() {
  client_ = nullptr;
  delete this;
}

void MotermDriver::SendData(const void* bytes, size_t num_bytes) {
  DCHECK(client_);
  DCHECK(!is_closed_);

  if (icanon_) {
    for (size_t i = 0; i < num_bytes; i++)
      HandleCanonicalModeInput(static_cast<const uint8_t*>(bytes)[i]);
  } else {
    // If not in canonical ("cooked") mode, just send data.
    const uint8_t* b = static_cast<const uint8_t*>(bytes);
    for (size_t i = 0; i < num_bytes; i++)
      send_data_queue_.push_back(b[i]);

    CompletePendingReads();
  }
}

MotermDriver::MotermDriver(Client* client,
                           mojo::InterfaceRequest<mojo::files::File> request)
    : client_(client),
      is_closed_(false),
      binding_(this, request.Pass()),
      icanon_(true),
      icrnl_(true),
      veof_(kEOT),
      verase_(kDEL),
      onlcr_(true),
      weak_factory_(this) {
  DCHECK(client_);
}

MotermDriver::~MotermDriver() {
  if (client_) {
    // Invalidate weak pointers now, to make sure the client doesn't call us.
    weak_factory_.InvalidateWeakPtrs();
    client_->OnDestroyed();
  }
}

void MotermDriver::HandleCanonicalModeInput(uint8_t ch) {
  DCHECK(icanon_);

  // Translate CR to NL, if appropriate.
  if (ch == kCR && icrnl_)
    ch = kNL;

  // Newline.
  // TODO(vtl): In addition to NL, we're supposed to handle settable EOL and
  // EOL2.
  if (ch == kNL) {  // Newline.
    input_line_queue_.push_back(ch);
    HandleOutput(&ch, 1);
    FlushInputLine();
    return;
  }

  // EOF at beginning of line.
  if (ch == veof_ && input_line_queue_.empty()) {
    // Don't add the character. Just flush and nuke ourselves.
    FlushInputLine();
    delete this;
    return;
  }

  if (ch == verase_) {  // Erase (backspace).
    if (!input_line_queue_.empty()) {
      // TODO(vtl): This is wrong for utf-8 (see Linux's IUTF8).
      input_line_queue_.pop_back();
      HandleOutput(reinterpret_cast<const uint8_t*>("\x08 \x08"), 3);
    }  // Else do nothing.
    return;
  }

  // Everything else.
  // TODO(vtl): Probably want to display control characters as ^X (e.g.).
  // TODO(vtl): Handle ^W.
  input_line_queue_.push_back(ch);
  HandleOutput(&ch, 1);
}

void MotermDriver::CompletePendingReads() {
  while (send_data_queue_.size() && pending_read_queue_.size()) {
    PendingRead pending_read = pending_read_queue_.front();
    pending_read_queue_.pop_front();

    size_t data_size = std::min(static_cast<size_t>(pending_read.num_bytes),
                                send_data_queue_.size());
    mojo::Array<uint8_t> data(data_size);
    for (size_t i = 0; i < data_size; i++) {
      data[i] = send_data_queue_[i];
      // In canonical mode, each read only gets a single line.
      if (icanon_ && data[i] == kNL) {
        data_size = i + 1;
        data.resize(data_size);
        break;
      }
    }
    send_data_queue_.erase(send_data_queue_.begin(),
                           send_data_queue_.begin() + data_size);

    pending_read.callback.Run(mojo::files::ERROR_OK, data.Pass());
  }
}

void MotermDriver::FlushInputLine() {
  for (size_t i = 0; i < input_line_queue_.size(); i++)
    send_data_queue_.push_back(input_line_queue_[i]);
  input_line_queue_.clear();
  CompletePendingReads();
}

void MotermDriver::HandleOutput(const uint8_t* bytes, size_t num_bytes) {
  // Can we be smarter and not always copy?
  std::vector<uint8_t> translated_bytes;
  translated_bytes.reserve(num_bytes);

  for (size_t i = 0; i < num_bytes; i++) {
    uint8_t ch = bytes[i];
    if (ch == kNL && onlcr_) {
      translated_bytes.push_back(kCR);
      translated_bytes.push_back(kNL);
    } else {
      translated_bytes.push_back(ch);
    }
  }

  // TODO(vtl): It seems extremely unlikely that we'd overlow a |uint32_t| here
  // (but it's theoretically possible). But perhaps we should handle it more
  // gracefully if it ever comes up.
  CHECK_LE(translated_bytes.size(), std::numeric_limits<uint32_t>::max());
  client_->OnDataReceived(translated_bytes.data(),
                          static_cast<uint32_t>(translated_bytes.size()));
}

void MotermDriver::Close(const CloseCallback& callback) {
  if (is_closed_) {
    callback.Run(mojo::files::ERROR_CLOSED);
    return;
  }

  is_closed_ = true;
  callback.Run(mojo::files::ERROR_OK);

  // TODO(vtl): Call pending read callbacks?

  client_->OnClosed();
}

void MotermDriver::Read(uint32_t num_bytes_to_read,
                        int64_t offset,
                        mojo::files::Whence whence,
                        const ReadCallback& callback) {
  if (is_closed_) {
    callback.Run(mojo::files::ERROR_CLOSED, mojo::Array<uint8_t>());
    return;
  }

  if (offset != 0 || whence != mojo::files::WHENCE_FROM_CURRENT) {
    // TODO(vtl): Is this the "right" behavior?
    callback.Run(mojo::files::ERROR_INVALID_ARGUMENT, mojo::Array<uint8_t>());
    return;
  }

  if (!num_bytes_to_read) {
    callback.Run(mojo::files::ERROR_OK, mojo::Array<uint8_t>());
    return;
  }

  pending_read_queue_.push_back(PendingRead(num_bytes_to_read, callback));
  CompletePendingReads();
}

void MotermDriver::Write(mojo::Array<uint8_t> bytes_to_write,
                         int64_t offset,
                         mojo::files::Whence whence,
                         const WriteCallback& callback) {
  DCHECK(!bytes_to_write.is_null());

  if (is_closed_) {
    callback.Run(mojo::files::ERROR_CLOSED, 0);
    return;
  }

  if (offset != 0 || whence != mojo::files::WHENCE_FROM_CURRENT) {
    // TODO(vtl): Is this the "right" behavior?
    callback.Run(mojo::files::ERROR_INVALID_ARGUMENT, 0);
    return;
  }

  if (!bytes_to_write.size()) {
    callback.Run(mojo::files::ERROR_OK, 0);
    return;
  }

  HandleOutput(&bytes_to_write.front(), bytes_to_write.size());

  // TODO(vtl): Is this OK if the client detached (and we're destroyed?).
  callback.Run(mojo::files::ERROR_OK,
               static_cast<uint32_t>(bytes_to_write.size()));
}

void MotermDriver::ReadToStream(mojo::ScopedDataPipeProducerHandle source,
                                int64_t offset,
                                mojo::files::Whence whence,
                                int64_t num_bytes_to_read,
                                const ReadToStreamCallback& callback) {
  if (is_closed_) {
    callback.Run(mojo::files::ERROR_CLOSED);
    return;
  }

  // TODO(vtl)
  NOTIMPLEMENTED();
  callback.Run(mojo::files::ERROR_UNIMPLEMENTED);
}

void MotermDriver::WriteFromStream(mojo::ScopedDataPipeConsumerHandle sink,
                                   int64_t offset,
                                   mojo::files::Whence whence,
                                   const WriteFromStreamCallback& callback) {
  if (is_closed_) {
    callback.Run(mojo::files::ERROR_CLOSED);
    return;
  }

  // TODO(vtl)
  NOTIMPLEMENTED();
  callback.Run(mojo::files::ERROR_UNIMPLEMENTED);
}

void MotermDriver::Tell(const TellCallback& callback) {
  if (is_closed_) {
    callback.Run(mojo::files::ERROR_CLOSED, 0);
    return;
  }

  // TODO(vtl): Is this what we want? (Also is "unavailable" right? Maybe
  // unsupported/EINVAL is better.)
  callback.Run(mojo::files::ERROR_UNAVAILABLE, 0);
}

void MotermDriver::Seek(int64_t offset,
                        mojo::files::Whence whence,
                        const SeekCallback& callback) {
  if (is_closed_) {
    callback.Run(mojo::files::ERROR_CLOSED, 0);
    return;
  }

  // TODO(vtl): Is this what we want? (Also is "unavailable" right? Maybe
  // unsupported/EINVAL is better.)
  callback.Run(mojo::files::ERROR_UNAVAILABLE, 0);
}

void MotermDriver::Stat(const StatCallback& callback) {
  if (is_closed_) {
    callback.Run(mojo::files::ERROR_CLOSED, nullptr);
    return;
  }

  // TODO(vtl)
  NOTIMPLEMENTED();
  callback.Run(mojo::files::ERROR_UNIMPLEMENTED, nullptr);
}

void MotermDriver::Truncate(int64_t size, const TruncateCallback& callback) {
  if (is_closed_) {
    callback.Run(mojo::files::ERROR_CLOSED);
    return;
  }

  // TODO(vtl): Is this what we want? (Also is "unavailable" right? Maybe
  // unsupported/EINVAL is better.)
  callback.Run(mojo::files::ERROR_UNAVAILABLE);
}

void MotermDriver::Touch(mojo::files::TimespecOrNowPtr atime,
                         mojo::files::TimespecOrNowPtr mtime,
                         const TouchCallback& callback) {
  if (is_closed_) {
    callback.Run(mojo::files::ERROR_CLOSED);
    return;
  }

  // TODO(vtl): Is this what we want? (Also is "unavailable" right? Maybe
  // unsupported/EINVAL is better.)
  callback.Run(mojo::files::ERROR_UNAVAILABLE);
}

void MotermDriver::Dup(mojo::InterfaceRequest<mojo::files::File> file,
                       const DupCallback& callback) {
  if (is_closed_) {
    callback.Run(mojo::files::ERROR_CLOSED);
    return;
  }

  // TODO(vtl): Is this what we want? (Also is "unavailable" right? Maybe
  // unsupported/EINVAL is better.)
  callback.Run(mojo::files::ERROR_UNAVAILABLE);
}

void MotermDriver::Reopen(mojo::InterfaceRequest<mojo::files::File> file,
                          uint32_t open_flags,
                          const ReopenCallback& callback) {
  if (is_closed_) {
    callback.Run(mojo::files::ERROR_CLOSED);
    return;
  }

  // TODO(vtl): Is this what we want? (Also is "unavailable" right? Maybe
  // unsupported/EINVAL is better.)
  callback.Run(mojo::files::ERROR_UNAVAILABLE);
}

void MotermDriver::AsBuffer(const AsBufferCallback& callback) {
  if (is_closed_) {
    callback.Run(mojo::files::ERROR_CLOSED, mojo::ScopedSharedBufferHandle());
    return;
  }

  // TODO(vtl): Is this what we want? (Also is "unavailable" right? Maybe
  // unsupported/EINVAL is better.)
  callback.Run(mojo::files::ERROR_UNAVAILABLE,
               mojo::ScopedSharedBufferHandle());
}

void MotermDriver::Ioctl(uint32_t request,
                         mojo::Array<uint32_t> in_values,
                         const IoctlCallback& callback) {
  if (is_closed_) {
    callback.Run(mojo::files::ERROR_CLOSED, mojo::Array<uint32_t>());
    return;
  }

  if (request != mojo::files::kIoctlTerminal) {
    callback.Run(mojo::files::ERROR_UNIMPLEMENTED, mojo::Array<uint32_t>());
    return;
  }

  // "Is TTY?" Yes.
  if (!in_values || !in_values.size()) {
    callback.Run(mojo::files::ERROR_OK, mojo::Array<uint32_t>());
    return;
  }

  switch (in_values[0]) {
    case mojo::files::kIoctlTerminalGetSettings:
      IoctlGetSettings(in_values.Pass(), callback);
      return;
    case mojo::files::kIoctlTerminalSetSettings:
      IoctlSetSettings(in_values.Pass(), callback);
      return;
    case mojo::files::kIoctlTerminalGetWindowSize:
    case mojo::files::kIoctlTerminalSetWindowSize:
      NOTIMPLEMENTED();
      callback.Run(mojo::files::ERROR_UNIMPLEMENTED, mojo::Array<uint32_t>());
      return;
    default:
      callback.Run(mojo::files::ERROR_UNIMPLEMENTED, mojo::Array<uint32_t>());
      return;
  }
}

void MotermDriver::IoctlGetSettings(mojo::Array<uint32_t> in_values,
                                    const IoctlCallback& callback) {
  if (in_values.size() != 1u) {
    callback.Run(mojo::files::ERROR_INVALID_ARGUMENT, mojo::Array<uint32_t>());
    return;
  }

  auto out_values = mojo::Array<uint32_t>::New(kTotalFieldCount);

  // TODO(vtl): Add support for various things. Also, some values should be
  // hard-coded.

  // iflag:
  if (icrnl_)
    out_values[kIFlagIdx] |= mojo::files::kIoctlTerminalTermiosIFlagICRNL;

  // oflag:
  if (onlcr_)
    out_values[kOFlagIdx] |= mojo::files::kIoctlTerminalTermiosOFlagONLCR;

  // lflag:
  if (icanon_)
    out_values[kLFlagIdx] |= mojo::files::kIoctlTerminalTermiosLFlagICANON;

  // cc:
  out_values[kVEraseIdx] = verase_;
  out_values[kVEOFIdx] = veof_;

  callback.Run(mojo::files::ERROR_OK, out_values.Pass());
}

void MotermDriver::IoctlSetSettings(mojo::Array<uint32_t> in_values,
                                    const IoctlCallback& callback) {
  callback.Run(IoctlSetSettingsHelper(in_values.Pass()),
               mojo::Array<uint32_t>());
}

mojo::files::Error MotermDriver::IoctlSetSettingsHelper(
    mojo::Array<uint32_t> in_values) {
  // Note: "termios" offsets (and sizes) are increased by 1, to accomodate the
  // subrequest at index 0.

  // The "cc" values are optional.
  if (in_values.size() < 1 + kBaseFieldCount)
    return mojo::files::ERROR_INVALID_ARGUMENT;

  // TODO(vtl): Add support for various things. Also, some values can't be
  // changed.

  // iflag:
  icrnl_ = !!(in_values[1 + kIFlagIdx] &
              mojo::files::kIoctlTerminalTermiosIFlagICRNL);

  // oflag:
  onlcr_ = !!(in_values[1 + kOFlagIdx] &
              mojo::files::kIoctlTerminalTermiosOFlagONLCR);

  // lflag:
  icanon_ = !!(in_values[1 + kLFlagIdx] &
               mojo::files::kIoctlTerminalTermiosLFlagICANON);

  // TODO(vtl): Check that ispeed and ospeed are not set?

  // cc:
  if (1 + kVEraseIdx < in_values.size()) {
    uint32_t value = in_values[1 + kVEraseIdx];
    if (value > std::numeric_limits<uint8_t>::max())
      return mojo::files::ERROR_INVALID_ARGUMENT;
    verase_ = static_cast<uint8_t>(value);
  }
  if (1 + kVEOFIdx < in_values.size()) {
    uint32_t value = in_values[1 + kVEOFIdx];
    if (value > std::numeric_limits<uint8_t>::max())
      return mojo::files::ERROR_INVALID_ARGUMENT;
    veof_ = static_cast<uint8_t>(value);
  }

  return mojo::files::ERROR_OK;
}
