/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#include "cmCursesStringWidget.h"

#include <cstdio>

#include "cmCursesForm.h"
#include "cmCursesMainForm.h"
#include "cmCursesStandardIncludes.h"
#include "cmCursesWidget.h"
#include "cmStateTypes.h"

inline int ctrl(int z)
{
  return (z & 037);
}

cmCursesStringWidget::cmCursesStringWidget(int width, int height, int left,
                                           int top)
  : cmCursesWidget(width, height, left, top)
{
  this->InEdit = false;
  this->Type = cmStateEnums::STRING;
  set_field_fore(this->Field, A_NORMAL);
  set_field_back(this->Field, A_STANDOUT);
  field_opts_off(this->Field, O_STATIC);
}

void cmCursesStringWidget::OnTab(cmCursesMainForm* /*unused*/,
                                 WINDOW* /*unused*/)
{
  // FORM* form = fm->GetForm();
}

void cmCursesStringWidget::OnReturn(cmCursesMainForm* fm, WINDOW* /*unused*/)
{
  if (this->InEdit) {
    cmCursesForm::LogMessage("String widget leaving edit.");
    this->InEdit = false;
    fm->PrintKeys();
    this->OriginalString.clear();
    // trick to force forms to update the field buffer
    FORM* form = fm->GetForm();
    form_driver(form, REQ_NEXT_FIELD);
    form_driver(form, REQ_PREV_FIELD);
    this->Done = true;
  } else {
    cmCursesForm::LogMessage("String widget entering edit.");
    this->InEdit = true;
    fm->PrintKeys();
    this->OriginalString = field_buffer(this->Field, 0);
  }
}

void cmCursesStringWidget::OnType(int& key, cmCursesMainForm* fm,
                                  WINDOW* /*unused*/)
{
  form_driver(fm->GetForm(), key);
}

bool cmCursesStringWidget::HandleInput(int& key, cmCursesMainForm* fm,
                                       WINDOW* w)
{
  int x;
  int y;

  FORM* form = fm->GetForm();
  // when not in edit mode, edit mode is entered by pressing enter or i (vim
  // binding)
  // 10 == enter
  if (!this->InEdit && (key != 10 && key != KEY_ENTER && key != 'i')) {
    return false;
  }

  this->OriginalString.clear();
  this->Done = false;

  char debugMessage[128];

  // <Enter> is used to change edit mode (like <Esc> in vi).
  while (!this->Done) {
    sprintf(debugMessage, "String widget handling input, key: %d", key);
    cmCursesForm::LogMessage(debugMessage);

    fm->PrintKeys();

    getmaxyx(stdscr, y, x);
    // If window too small, handle 'q' only
    if (x < cmCursesMainForm::MIN_WIDTH || y < cmCursesMainForm::MIN_HEIGHT) {
      // quit
      if (key == 'q') {
        return false;
      }
      key = getch();
      continue;
    }

    // If resize occurred during edit, move out of edit mode
    if (!this->InEdit && (key != 10 && key != KEY_ENTER && key != 'i')) {
      return false;
    }
    // enter edit with return and i (vim binding)
    if (!this->InEdit && (key == 10 || key == KEY_ENTER || key == 'i')) {
      this->OnReturn(fm, w);
    }
    // leave edit with return (but not i -- not a toggle)
    else if (this->InEdit && (key == 10 || key == KEY_ENTER)) {
      this->OnReturn(fm, w);
    } else if (key == KEY_DOWN || key == ctrl('n') || key == KEY_UP ||
               key == ctrl('p') || key == KEY_NPAGE || key == ctrl('d') ||
               key == KEY_PPAGE || key == ctrl('u')) {
      this->InEdit = false;
      this->OriginalString.clear();
      // trick to force forms to update the field buffer
      form_driver(form, REQ_NEXT_FIELD);
      form_driver(form, REQ_PREV_FIELD);
      return false;
    }
    // esc
    else if (key == 27) {
      if (this->InEdit) {
        this->InEdit = false;
        fm->PrintKeys();
        this->SetString(this->OriginalString);
        this->OriginalString.clear();
        touchwin(w);
        wrefresh(w);
        return true;
      }
    } else if (key == 9) {
      this->OnTab(fm, w);
    } else if (key == KEY_LEFT || key == ctrl('b')) {
      form_driver(form, REQ_PREV_CHAR);
    } else if (key == KEY_RIGHT || key == ctrl('f')) {
      form_driver(form, REQ_NEXT_CHAR);
    } else if (key == ctrl('k')) {
      form_driver(form, REQ_CLR_EOL);
    } else if (key == ctrl('a') || key == KEY_HOME) {
      form_driver(form, REQ_BEG_FIELD);
    } else if (key == ctrl('e') || key == KEY_END) {
      form_driver(form, REQ_END_FIELD);
    } else if (key == 127 || key == KEY_BACKSPACE) {
      FIELD* cur = current_field(form);
      form_driver(form, REQ_DEL_PREV);
      if (current_field(form) != cur) {
        set_current_field(form, cur);
      }
    } else if (key == ctrl('d') || key == KEY_DC) {
      form_driver(form, REQ_DEL_CHAR);
    } else {
      this->OnType(key, fm, w);
    }
    if (!this->Done) {
      touchwin(w);
      wrefresh(w);

      key = getch();
    }
  }
  return true;
}

void cmCursesStringWidget::SetString(const std::string& value)
{
  this->SetValue(value);
}

const char* cmCursesStringWidget::GetString()
{
  return this->GetValue();
}

const char* cmCursesStringWidget::GetValue()
{
  return field_buffer(this->Field, 0);
}

bool cmCursesStringWidget::PrintKeys()
{
  int x;
  int y;
  getmaxyx(stdscr, y, x);
  if (x < cmCursesMainForm::MIN_WIDTH || y < cmCursesMainForm::MIN_HEIGHT) {
    return false;
  }
  if (this->InEdit) {
    char fmt_s[] = "%s";
    // Clean the toolbar
    curses_move(y - 4, 0);
    clrtoeol();
    curses_move(y - 3, 0);
    printw(fmt_s, "Editing option, press [enter] to confirm");
    clrtoeol();
    curses_move(y - 2, 0);
    printw(fmt_s, "                press [esc] to cancel");
    clrtoeol();
    curses_move(y - 1, 0);
    clrtoeol();

    return true;
  }
  return false;
}
