// 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 "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