/****************************************************************************
 * apps/examples/pdcurses/tui.c
 * Textual User Interface
 *
 *   Author : P.J. Kunst <kunst@prl.philips.nl>
 *   Date   : 25-02-93
 *
 *   Purpose: This program demonstrates the use of the 'curses' library
 *            for the creation of (simple) menu-operated programs.
 *            In the PDCurses version, use is made of colors for the
 *            highlighting of subwindows (title bar, status bar etc).
 *
 *   Acknowledgement: some ideas were borrowed from Mark Hessling's
 *                    version of the 'testcurs' program.
 *
 * $Id: tuidemo.c,v 1.22 2008/07/14 12:35:23 wmcbrine Exp $
 *
 *   Copyright (C) 2017 Gregory Nutt. All rights reserved.
 *   Adapted by: Gregory Nutt <gnutt@nuttx.org>
 *
 * Adapted from the original public domain pdcurses by Gregory Nutt and
 * released as part of NuttX under the 3-clause BSD license:
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name NuttX nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/****************************************************************************
 * Included Files
 ****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>

#include "tui.h"

/****************************************************************************
 * Pre-processor Definitions
 ****************************************************************************/

/* Change this if source at other location */

#define FNAME  "../demos/tui.c"

/****************************************************************************
 * Private Function Prototypes
 ****************************************************************************/

static void address(void);
static void sub0(void);
static void sub1(void);
static void sub2(void);
static void sub3(void);
static void func1(void);
static void func2(void);
static void subfunc1(void);
static void subfunc2(void);
static void subsub(void);

/****************************************************************************
 * Private Data
 ****************************************************************************/

static const char *g_fieldname[6] =
{
  "Name", "Street", "City", "State", "Country", (char *)0
};

menu g_mainmenu[] =
{
  {"Asub", sub0, "Go inside first submenu"},
  {"Bsub", sub1, "Go inside second submenu"},
  {"Csub", sub2, "Go inside third submenu"},
  {"Dsub", sub3, "Go inside fourth submenu"},
  {"", (FUNC)0, ""}             /* always add this as the last item! */
};

static const menu g_submenu0[] =
{
  {"Exit", tui_exit, "Terminate program"},
  {"", (FUNC)0, ""}
};

static const menu g_submenu1[] =
{
  {"OneBeep", func1, "Sound one beep"},
  {"TwoBeeps", func2, "Sound two beeps"},
  {"", (FUNC)0, ""}
};

static const menu g_submenu2[] =
{
  {"Browse", subfunc1, "Source file lister"},
  {"Input", subfunc2, "Interactive file lister"},
  {"Address", address, "Get address data"},
  {"", (FUNC)0, ""}
};

static const menu g_submenu3[] =
{
  {"SubSub", subsub, "Go inside sub-submenu"},
  {"", (FUNC)0, ""}
};

/****************************************************************************
 * Private Functions
 ****************************************************************************/

static void address(void)
{
  char *fieldbuf[5];
  WINDOW *wbody = bodywin();
  int field = 50;
  int i;

  for (i = 0; i < 5; i++)
    {
      fieldbuf[i] = calloc(1, field + 1);
    }

  if (getstrings(g_fieldname, fieldbuf, field) != KEY_ESC)
    {
      for (i = 0; g_fieldname[i]; i++)
        {
          wprintw(wbody, "%10s : %s\n", g_fieldname[i], fieldbuf[i]);
        }

      wrefresh(wbody);
    }

  for (i = 0; i < 5; i++)
    {
      free(fieldbuf[i]);
    }
}

static char *getfname(char *desc, char *fname, int field)
{
  char *fieldname[2];
  char *fieldbuf[1];

  fieldname[0] = desc;
  fieldname[1] = 0;
  fieldbuf[0]  = fname;

  return (getstrings((const char **)fieldname, fieldbuf, field) == KEY_ESC) ? NULL : fname;
}

static void showfile(char *fname)
{
  FILE *fp;
  char buf[MAXSTRLEN];
  bool ateof = false;
  int bh = bodylen();
  int i;

  statusmsg("FileBrowser: Hit key to continue, Q to quit");

  if ((fp = fopen(fname, "r")) != NULL) /* file available? */
    {
      while (!ateof)
        {
          clsbody();

          for (i = 0; i < bh - 1 && !ateof; i++)
            {
              buf[0] = '\0';
              fgets(buf, MAXSTRLEN, fp);

              if (strlen(buf))
                {
                  bodymsg(buf);
                }
              else
                {
                  ateof = true;
                }
            }

          switch (waitforkey())
            {
            case 'Q':
            case 'q':
            case 0x1b:
              ateof = true;
              break;
            }
        }

      fclose(fp);
    }
  else
    {
      sprintf(buf, "ERROR: file '%s' not found", fname);
      errormsg(buf);
    }
}

static void sub0(void)
{
  domenu(g_submenu0);
}

static void sub1(void)
{
  domenu(g_submenu1);
}

static void sub2(void)
{
  domenu(g_submenu2);
}

static void sub3(void)
{
  domenu(g_submenu3);
}

static void func1(void)
{
  beep();
  bodymsg("One beep! ");
}

static void func2(void)
{
  beep();
  bodymsg("Two beeps! ");
  beep();
}

static void subfunc1(void)
{
  showfile(FNAME);
}

static void subfunc2(void)
{
  char fname[MAXSTRLEN];

  strcpy(fname, FNAME);
  if (getfname("File to browse:", fname, 50))
    {
      showfile(fname);
    }
}

static void subsub(void)
{
  domenu(g_submenu2);
}

/****************************************************************************
 * Public Functions
 ****************************************************************************/

#ifdef CONFIG_BUILD_KERNEL
int main(int argc, FAR char *argv[])
#else
int tui_main(int argc, char *argv[])
#endif
{
#ifdef CONFIG_LIBC_LOCALE
  setlocale(LC_ALL, "");
#endif

  startmenu(g_mainmenu, "TUI - 'textual user interface' demonstration program");
  return 0;
}
