// 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());
    auto data = mojo::Array<uint8_t>::New(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;
  }

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

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

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