/*============================================================================
  CMake - Cross Platform Makefile Generator
  Copyright 2000-2009 Kitware, Inc., Insight Software Consortium

  Distributed under the OSI-approved BSD License (the "License");
  see accompanying file Copyright.txt for details.

  This software is distributed WITHOUT ANY WARRANTY; without even the
  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  See the License for more information.
============================================================================*/
#include "../cmSystemTools.h"
#include "../cmake.h"
#include "../cmVersion.h"
#include "cmCursesLongMessageForm.h"
#include "cmCursesMainForm.h"

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

cmCursesLongMessageForm::cmCursesLongMessageForm(std::vector<std::string>
                                                 const& messages, const char*
                                                 title)
{
  // Append all messages into on big string
  std::vector<std::string>::const_iterator it;
  for(it=messages.begin(); it != messages.end(); it++)
    {
    this->Messages += (*it);
    // Add one blank line after each message
    this->Messages += "\n\n";
    }
  this->Title = title;
  this->Fields[0] = 0;
  this->Fields[1] = 0;
}

cmCursesLongMessageForm::~cmCursesLongMessageForm()
{
  if (this->Fields[0])
    {
    free_field(this->Fields[0]);
    }
}


void cmCursesLongMessageForm::UpdateStatusBar()
{
  int x,y;
  getmaxyx(stdscr, y, x);

  char bar[cmCursesMainForm::MAX_WIDTH];
  size_t size = strlen(this->Title.c_str());
  if ( size >= cmCursesMainForm::MAX_WIDTH )
    {
    size = cmCursesMainForm::MAX_WIDTH-1;
    }
  strncpy(bar, this->Title.c_str(), size);
  for(size_t i=size-1; i<cmCursesMainForm::MAX_WIDTH; i++) bar[i] = ' ';

  int width;
  if (x < cmCursesMainForm::MAX_WIDTH )
    {
    width = x;
    }
  else
    {
    width = cmCursesMainForm::MAX_WIDTH-1;
    }

  bar[width] = '\0';

  char version[cmCursesMainForm::MAX_WIDTH];
  char vertmp[128];
  sprintf(vertmp,"CMake Version %s", cmVersion::GetCMakeVersion());
  size_t sideSpace = (width-strlen(vertmp));
  for(size_t i=0; i<sideSpace; i++) { version[i] = ' '; }
  sprintf(version+sideSpace, "%s", vertmp);
  version[width] = '\0';

  char fmt_s[] = "%s";
  curses_move(y-4,0);
  attron(A_STANDOUT);
  printw(fmt_s, bar);
  attroff(A_STANDOUT);
  curses_move(y-3,0);
  printw(fmt_s, version);
  pos_form_cursor(this->Form);
}

void cmCursesLongMessageForm::PrintKeys()
{
  int x,y;
  getmaxyx(stdscr, y, x);
  if ( x < cmCursesMainForm::MIN_WIDTH  ||
       y < cmCursesMainForm::MIN_HEIGHT )
    {
    return;
    }
  char firstLine[512];
  sprintf(firstLine,  "Press [e] to exit help");

  char fmt_s[] = "%s";
  curses_move(y-2,0);
  printw(fmt_s, firstLine);
  pos_form_cursor(this->Form);

}

void cmCursesLongMessageForm::Render(int, int, int, int)
{
  int x,y;
  getmaxyx(stdscr, y, x);

  if (this->Form)
    {
    unpost_form(this->Form);
    free_form(this->Form);
    this->Form = 0;
    }

  const char* msg = this->Messages.c_str();

  curses_clear();

  if (this->Fields[0])
    {
    free_field(this->Fields[0]);
    this->Fields[0] = 0;
    }

  this->Fields[0] = new_field(y-6, x-2, 1, 1, 0, 0);

  field_opts_off(this->Fields[0],  O_STATIC);

  this->Form = new_form(this->Fields);
  post_form(this->Form);

  int i=0;
  form_driver(this->Form, REQ_BEG_FIELD);
  while(msg[i] != '\0' && i < 60000)
    {
    if (msg[i] == '\n' && msg[i+1] != '\0')
      {
      form_driver(this->Form, REQ_NEW_LINE);
      }
    else
      {
      form_driver(this->Form, msg[i]);
      }
    i++;
    }
  form_driver(this->Form, REQ_BEG_FIELD);

  this->UpdateStatusBar();
  this->PrintKeys();
  touchwin(stdscr);
  refresh();

}

void cmCursesLongMessageForm::HandleInput()
{
  if (!this->Form)
    {
    return;
    }

  char debugMessage[128];

  for(;;)
    {
    int key = getch();

    sprintf(debugMessage, "Message widget handling input, key: %d", key);
    cmCursesForm::LogMessage(debugMessage);

    // quit
    if ( key == 'o' || key == 'e' )
      {
      break;
      }
    else if ( key == KEY_DOWN || key == ctrl('n') )
      {
      form_driver(this->Form, REQ_SCR_FLINE);
      }
    else if ( key == KEY_UP  || key == ctrl('p') )
      {
      form_driver(this->Form, REQ_SCR_BLINE);
      }
    else if ( key == KEY_NPAGE || key == ctrl('d') )
      {
      form_driver(this->Form, REQ_SCR_FPAGE);
      }
    else if ( key == KEY_PPAGE || key == ctrl('u') )
      {
      form_driver(this->Form, REQ_SCR_BPAGE);
      }

    this->UpdateStatusBar();
    this->PrintKeys();
    touchwin(stdscr);
    wrefresh(stdscr);
    }

}
