// Copyright 2016 The Fuchsia 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 "topaz/app/term/term_model.h"

#include <string.h>

#include <algorithm>
#include <limits>

#include "src/lib/fxl/logging.h"

namespace term {
namespace {

// Moterm -> teken conversions:

teken_pos_t MotermToTekenSize(const TermModel::Size& size) {
  FXL_DCHECK(size.rows <= std::numeric_limits<teken_unit_t>::max());
  FXL_DCHECK(size.columns <= std::numeric_limits<teken_unit_t>::max());
  teken_pos_t rv = {static_cast<teken_unit_t>(size.rows),
                    static_cast<teken_unit_t>(size.columns)};
  return rv;
}

// Teken -> term conversions:

TermModel::Position TekenToMotermPosition(const teken_pos_t& position) {
  return TermModel::Position(static_cast<int>(position.tp_row),
                             static_cast<int>(position.tp_col));
}

TermModel::Size TekenToMotermSize(const teken_pos_t& size) {
  return TermModel::Size(size.tp_row, size.tp_col);
}

TermModel::Rectangle TekenToMotermRectangle(const teken_rect_t& rectangle) {
  return TermModel::Rectangle(
      static_cast<int>(rectangle.tr_begin.tp_row),
      static_cast<int>(rectangle.tr_begin.tp_col),
      rectangle.tr_end.tp_row - rectangle.tr_begin.tp_row,
      rectangle.tr_end.tp_col - rectangle.tr_begin.tp_col);
}

TermModel::Color TekenToMotermColor(teken_color_t color, bool bold) {
  static const uint8_t rgb[TC_NCOLORS][3] = {
      {0x00, 0x00, 0x00},  // Black.
      {0x80, 0x00, 0x00},  // Red.
      {0x00, 0x80, 0x00},  // Green.
      {0x80, 0x80, 0x00},  // Yellow (even if teken thinks it's brown).
      {0x00, 0x00, 0x80},  // Blue.
      {0x80, 0x00, 0x80},  // Magenta.
      {0x00, 0x80, 0x80},  // Cyan.
      {0xc0, 0xc0, 0xc0}   // White.
  };
  static const uint8_t bold_rgb[TC_NCOLORS][3] = {
      {0x80, 0x80, 0x80},  // Black.
      {0xff, 0x00, 0x00},  // Red.
      {0x00, 0xff, 0x00},  // Green.
      {0xff, 0xff, 0x00},  // Yellow (even if teken thinks it's brown).
      {0x00, 0x00, 0xff},  // Blue.
      {0xff, 0x00, 0xff},  // Magenta.
      {0x00, 0xff, 0xff},  // Cyan.
      {0xff, 0xff, 0xff}   // White.
  };
  FXL_DCHECK(color < static_cast<unsigned>(TC_NCOLORS));
  return bold ? TermModel::Color(bold_rgb[color][0], bold_rgb[color][1],
                                 bold_rgb[color][2])
              : TermModel::Color(rgb[color][0], rgb[color][1], rgb[color][2]);
}

// Utility functions:

TermModel::Rectangle EnclosingRectangle(const TermModel::Rectangle& rect1,
                                        const TermModel::Rectangle& rect2) {
  if (rect1.IsEmpty())
    return rect2;
  if (rect2.IsEmpty())
    return rect1;

  int start_row = std::min(rect1.position.row, rect2.position.row);
  int start_col = std::min(rect1.position.column, rect2.position.column);
  // TODO(vtl): Some theoretical overflows here.
  int end_row =
      std::max(rect1.position.row + static_cast<int>(rect1.size.rows),
               rect2.position.row + static_cast<int>(rect2.size.rows));
  int end_col =
      std::max(rect1.position.column + static_cast<int>(rect1.size.columns),
               rect2.position.column + static_cast<int>(rect2.size.columns));
  FXL_DCHECK(start_row <= end_row);
  FXL_DCHECK(start_col <= end_col);
  return TermModel::Rectangle(start_row, start_col,
                              static_cast<unsigned>(end_row - start_row),
                              static_cast<unsigned>(end_col - start_col));
}

}  // namespace

const TermModel::Attributes TermModel::kAttributesBold;
const TermModel::Attributes TermModel::kAttributesUnderline;
const TermModel::Attributes TermModel::kAttributesBlink;

TermModel::Delegate::~Delegate() = default;

TermModel::TermModel(const Size& size, Delegate* delegate)
    : size_(size),
      delegate_(delegate),
      cursor_visible_(true),
      terminal_(),
      current_state_changes_() {
  FXL_DCHECK(size_.rows > 0u);
  FXL_DCHECK(size_.columns > 0u);

  num_chars_ = size_.rows * size_.columns;
  characters_.reset(new teken_char_t[num_chars_]);
  memset(characters_.get(), 0, num_chars_ * sizeof(teken_char_t));
  attributes_.reset(new teken_attr_t[num_chars_]);
  memset(attributes_.get(), 0, num_chars_ * sizeof(teken_attr_t));

  static const teken_funcs_t callbacks = {
      &TermModel::OnBellThunk,    &TermModel::OnCursorThunk,
      &TermModel::OnPutcharThunk, &TermModel::OnFillThunk,
      &TermModel::OnCopyThunk,    &TermModel::OnParamThunk,
      &TermModel::OnRespondThunk};
  teken_init(&terminal_, &callbacks, this);

  teken_pos_t s = MotermToTekenSize(size_);
  teken_set_winsize(&terminal_, &s);
}

TermModel::~TermModel() {}

void TermModel::ProcessInput(const void* input_bytes,
                             size_t num_input_bytes,
                             StateChanges* state_changes) {
  FXL_DCHECK(state_changes);
  FXL_DCHECK(!current_state_changes_);
  current_state_changes_ = state_changes;

  // Get the initial cursor position, so we'll be able to tell if it moved.
  teken_pos_t initial_cursor_pos = *teken_get_cursor(&terminal_);

  // Note: This may call some of our callbacks.
  char cr = '\r';
  const char* buffer = static_cast<const char*>(input_bytes);
  for (size_t i = 0; i < num_input_bytes; i++) {
    if (*buffer == '\n') {
      teken_input(&terminal_, &cr, 1);
    }
    teken_input(&terminal_, buffer++, 1);
  }

  teken_pos_t final_cursor_pos = *teken_get_cursor(&terminal_);
  if (initial_cursor_pos.tp_row != final_cursor_pos.tp_row ||
      initial_cursor_pos.tp_col != final_cursor_pos.tp_col) {
    state_changes->cursor_changed = true;
    // Update dirty rect to include old and new cursor positions.
    current_state_changes_->dirty_rect = EnclosingRectangle(
        current_state_changes_->dirty_rect,
        Rectangle(initial_cursor_pos.tp_row, initial_cursor_pos.tp_col, 1, 1));
    current_state_changes_->dirty_rect = EnclosingRectangle(
        current_state_changes_->dirty_rect,
        Rectangle(final_cursor_pos.tp_row, final_cursor_pos.tp_col, 1, 1));
  }

  current_state_changes_ = nullptr;
}

TermModel::Size TermModel::GetSize() const {
  // Teken isn't const-correct, sadly.
  return TekenToMotermSize(
      *teken_get_winsize(const_cast<teken_t*>(&terminal_)));
}

TermModel::Position TermModel::GetCursorPosition() const {
  // Teken isn't const-correct, sadly.
  return TekenToMotermPosition(
      *teken_get_cursor(const_cast<teken_t*>(&terminal_)));
}

bool TermModel::GetCursorVisibility() const {
  return cursor_visible_;
}

TermModel::CharacterInfo TermModel::GetCharacterInfoAt(
    const Position& position) const {
  FXL_DCHECK(position.row >= 0);
  FXL_DCHECK(position.row < static_cast<int>(GetSize().rows));
  FXL_DCHECK(position.column >= 0);
  FXL_DCHECK(position.column < static_cast<int>(GetSize().columns));

  uint32_t ch = characters_[position.row * size_.columns + position.column];
  const teken_attr_t& teken_attr =
      attributes_[position.row * size_.columns + position.column];
  Color fg = TekenToMotermColor(teken_attr.ta_fgcolor,
                                (teken_attr.ta_format & TF_BOLD));
  Color bg = TekenToMotermColor(teken_attr.ta_bgcolor, false);
  Attributes attr = 0;
  if ((teken_attr.ta_format & TF_BOLD))
    attr |= kAttributesBold;
  if ((teken_attr.ta_format & TF_UNDERLINE))
    attr |= kAttributesUnderline;
  if ((teken_attr.ta_format & TF_BLINK))
    attr |= kAttributesBlink;
  if ((teken_attr.ta_format & TF_REVERSE))
    std::swap(fg, bg);
  return CharacterInfo(ch, attr, fg, bg);
}

void TermModel::SetSize(const Size& size, bool reset) {
  FXL_DCHECK(size.rows > 0u);
  FXL_DCHECK(size.columns > 0u);
  Size old_size = size_;
  size_ = size;
  size_t new_num_chars = size_.rows * size_.columns;
  if (num_chars_ != new_num_chars) {
    teken_char_t* new_characters = new teken_char_t[new_num_chars];
    memset(new_characters, 0, new_num_chars * sizeof(teken_char_t));

    teken_attr_t* new_attributes = new teken_attr_t[new_num_chars];
    memset(new_attributes, 0, new_num_chars * sizeof(teken_attr_t));

    // FIXME(jpoichet) copy from bottom to top instead
    for (size_t r = 0; r < old_size.rows; ++r) {
      size_t bytes = old_size.columns * sizeof(teken_char_t);
      if (r * size_.columns + bytes > new_num_chars) {
        // Until we copy bottom to top, ignore the last line.
        break;
      }
      memcpy(new_characters + r * size_.columns,
             characters_.get() + r * old_size.columns,
             old_size.columns * sizeof(teken_char_t));
      memcpy(new_attributes + r * size_.columns,
             attributes_.get() + r * old_size.columns,
             old_size.columns * sizeof(teken_attr_t));
    }
    characters_.reset(new_characters);
    attributes_.reset(new_attributes);
    num_chars_ = new_num_chars;
  }

  teken_pos_t teken_size = {static_cast<teken_unit_t>(size.rows),
                            static_cast<teken_unit_t>(size.columns)};
  if (reset) {
    teken_set_winsize_noreset(&terminal_, &teken_size);
  } else {
    // We'll try a bit harder to keep a sensible cursor position.
    teken_pos_t cursor_pos =
        *teken_get_cursor(const_cast<teken_t*>(&terminal_));
    teken_set_winsize(&terminal_, &teken_size);
    if (cursor_pos.tp_row >= teken_size.tp_row)
      cursor_pos.tp_row = teken_size.tp_row - 1;
    if (cursor_pos.tp_col >= teken_size.tp_col)
      cursor_pos.tp_col = teken_size.tp_col - 1;
    teken_set_cursor(&terminal_, &cursor_pos);
  }
}

void TermModel::OnBell() {
  FXL_DCHECK(current_state_changes_);
  current_state_changes_->bell_count++;
}

void TermModel::OnCursor(const teken_pos_t* pos) {
  FXL_DCHECK(current_state_changes_);
  // Don't do anything. We'll just compare initial and final cursor positions.
}

void TermModel::OnPutchar(const teken_pos_t* pos,
                          teken_char_t ch,
                          const teken_attr_t* attr) {
  character_at(pos->tp_row, pos->tp_col) = ch;
  attribute_at(pos->tp_row, pos->tp_col) = *attr;

  // Update dirty rect.
  FXL_DCHECK(current_state_changes_);
  current_state_changes_->dirty_rect =
      EnclosingRectangle(current_state_changes_->dirty_rect,
                         Rectangle(pos->tp_row, pos->tp_col, 1, 1));
}

void TermModel::OnFill(const teken_rect_t* rect,
                       teken_char_t ch,
                       const teken_attr_t* attr) {
  for (size_t row = rect->tr_begin.tp_row; row < rect->tr_end.tp_row; row++) {
    for (size_t col = rect->tr_begin.tp_col; col < rect->tr_end.tp_col; col++) {
      character_at(row, col) = ch;
      attribute_at(row, col) = *attr;
    }
  }

  // Update dirty rect.
  FXL_DCHECK(current_state_changes_);
  current_state_changes_->dirty_rect = EnclosingRectangle(
      current_state_changes_->dirty_rect, TekenToMotermRectangle(*rect));
}

void TermModel::OnCopy(const teken_rect_t* rect, const teken_pos_t* pos) {
  unsigned height = rect->tr_end.tp_row - rect->tr_begin.tp_row;
  unsigned width = rect->tr_end.tp_col - rect->tr_begin.tp_col;

  // This is really a "move" (like |memmove()|) -- overlaps are likely. Process
  // the rows depending on which way (vertically) we're moving.
  if (pos->tp_row <= rect->tr_begin.tp_row) {
    // Start from the top row.
    for (unsigned row = 0; row < height; row++) {
      // Use |memmove()| here, to in case we're not moving vertically.
      memmove(&character_at(pos->tp_row + row, pos->tp_col),
              &character_at(rect->tr_begin.tp_row + row, pos->tp_col),
              width * sizeof(characters_[0]));
      memmove(&attribute_at(pos->tp_row + row, pos->tp_col),
              &attribute_at(rect->tr_begin.tp_row + row, pos->tp_col),
              width * sizeof(attributes_[0]));
    }
  } else {
    // Start from the bottom row.
    for (unsigned row = height; row > 0;) {
      row--;
      // We can use |memcpy()| here.
      memcpy(&character_at(pos->tp_row + row, pos->tp_col),
             &character_at(rect->tr_begin.tp_row + row, pos->tp_col),
             width * sizeof(characters_[0]));
      memcpy(&attribute_at(pos->tp_row + row, pos->tp_col),
             &attribute_at(rect->tr_begin.tp_row + row, pos->tp_col),
             width * sizeof(attributes_[0]));
    }
  }

  // Update dirty rect.
  FXL_DCHECK(current_state_changes_);
  current_state_changes_->dirty_rect = EnclosingRectangle(
      current_state_changes_->dirty_rect,
      Rectangle(static_cast<int>(pos->tp_row), static_cast<int>(pos->tp_col),
                width, height));
}

void TermModel::OnParam(int cmd, unsigned val) {
  FXL_DCHECK(current_state_changes_);

  // Note: |val| is usually a "boolean", except for |TP_SETBELLPD| (for which
  // |val| can be decomposed using |TP_SETBELLPD_{PITCH, DURATION}()|).
  switch (cmd) {
    case TP_SHOWCURSOR:
      cursor_visible_ = !!val;
      current_state_changes_->cursor_changed = true;
      break;
    case TP_KEYPADAPP:
      if (delegate_)
        delegate_->OnSetKeypadMode(!!val);
      break;
    case TP_AUTOREPEAT:
    case TP_SWITCHVT:
    case TP_132COLS:
    case TP_SETBELLPD:
    case TP_MOUSE:
      // TODO(vtl): TP_KEYPADAPP seems especially common.
      FXL_NOTIMPLEMENTED() << "OnParam(" << cmd << ", " << val << ")";
      break;
    default:
      FXL_NOTREACHED() << "OnParam(): unknown command: " << cmd;
      break;
  }
}

void TermModel::OnRespond(const void* buf, size_t size) {
  if (delegate_)
    delegate_->OnResponse(buf, size);
  else
    FXL_LOG(WARNING) << "Ignoring response: no delegate";
}

// static
void TermModel::OnBellThunk(void* ctx) {
  FXL_DCHECK(ctx);
  return static_cast<TermModel*>(ctx)->OnBell();
}

// static
void TermModel::OnCursorThunk(void* ctx, const teken_pos_t* pos) {
  FXL_DCHECK(ctx);
  return static_cast<TermModel*>(ctx)->OnCursor(pos);
}

// static
void TermModel::OnPutcharThunk(void* ctx,
                               const teken_pos_t* pos,
                               teken_char_t ch,
                               const teken_attr_t* attr) {
  FXL_DCHECK(ctx);
  return static_cast<TermModel*>(ctx)->OnPutchar(pos, ch, attr);
}

// static
void TermModel::OnFillThunk(void* ctx,
                            const teken_rect_t* rect,
                            teken_char_t ch,
                            const teken_attr_t* attr) {
  FXL_DCHECK(ctx);
  return static_cast<TermModel*>(ctx)->OnFill(rect, ch, attr);
}

// static
void TermModel::OnCopyThunk(void* ctx,
                            const teken_rect_t* rect,
                            const teken_pos_t* pos) {
  FXL_DCHECK(ctx);
  return static_cast<TermModel*>(ctx)->OnCopy(rect, pos);
}

// static
void TermModel::OnParamThunk(void* ctx, int cmd, unsigned val) {
  FXL_DCHECK(ctx);
  return static_cast<TermModel*>(ctx)->OnParam(cmd, val);
}

// static
void TermModel::OnRespondThunk(void* ctx, const void* buf, size_t size) {
  FXL_DCHECK(ctx);
  return static_cast<TermModel*>(ctx)->OnRespond(buf, size);
}

}  // namespace term
