
#include "gprompt.h"

#include "gmenu.h"
#include "ggui-message-c.h"
#include "gkbd_line.h"
#include "gcore/glaunch.h"

#ifndef WIN32
#include <unistd.h>
#include <sys/time.h>
#else
#include "gsys/win32.h"
#endif

static sic_task_t _sic_task_null = SIC_TASK_NULL;

static unsigned int timerstatus = 0;
static unsigned long timervalue = 0;

/* Reset timer value to val */
static void set_timer( unsigned long val)
{
#ifndef WIN32
    struct itimerval rttimer;

    rttimer.it_value.tv_sec = val;
    rttimer.it_value.tv_usec = 0;
    rttimer.it_interval.tv_sec = 0;
    rttimer.it_interval.tv_usec = 0;

    setitimer( ITIMER_REAL, &rttimer, NULL);
#endif
}

/* Set the timer status (on/off) */
void CFC_API xgag_settimer_status( int *status)
{
    timerstatus = (unsigned int) *status;
}

/* Get the timer status */
void CFC_API xgag_gettimer_status( int *status)
{
    *status = (int) timerstatus;
}

/* Set the timer in order to exit after 'ns' seconds doing nothing */
void CFC_API xgag_settimer( int *ns)
{
    int val;

    ggui_c_message(seve_d, "SIC", "Timer value : %d seconds", *ns);
    val = *ns;
    if (val < 0)
        val = 0;
    timerstatus = val > 0 ? 1 : 0;
    timervalue = (unsigned long)val;
}

/* Get the current timer (unit seconds) */
void CFC_API xgag_gettimer( int *ns)
{
    *ns = (int) timervalue;
}

/* Get the current timer command */
void CFC_API xgag_gettimer_command( CFC_FString command_line CFC_DECLARE_STRING_LENGTH( command_line))
{
    char tmp[COMMANDLENGTH];
    sic_get_alarm( tmp);
    CFC_c2f_strcpy( command_line, CFC_STRING_LENGTH( command_line), tmp) ;
}

/* Set the current timer command */
void CFC_API xgag_settimer_command( CFC_FString command_line CFC_DECLARE_STRING_LENGTH( command_line))
{
    char tmp[COMMANDLENGTH];
    CFC_f2c_strcpy( tmp, command_line, CFC_STRING_LENGTH( command_line)) ;
    sic_set_alarm( tmp);
}

static char s_gprompt_command_line[MAXBUF] = { '\0'};

void CFC_API gprompt_set_command_line( CFC_FString command_line CFC_DECLARE_STRING_LENGTH( command_line))
{
    CFC_f2c_strcpy( s_gprompt_command_line, command_line,
        CFC_STRING_LENGTH_MIN( command_line, sizeof(s_gprompt_command_line)));
}

static int s_init_gprompt_called = 0;

void CFC_API init_gprompt( )
{
    set_keyboard_handler( run_keyboard, s_gprompt_command_line);
    s_init_gprompt_called = 1;
}

/***************************************************************************
  If the main task runs in mono-user mode, an instance of SIC_KEYBOARD
  is created at each call of the task.
  Otherwise, the subsequent instances of the task will call prompt_loop with
  *code set to zero which override the executing task with a REMOTE_CLIENT
  control task, so that there is always a single instance of the named task
  currently running.
  ****************************************************************************/
void CFC_API prompt_loop( int *code)
{
    if (s_init_gprompt_called) {
        /* software calling new init routines */
    } else {
        sic_task_t keyboard_task;
        set_keyboard_handler( run_keyboard, s_gprompt_command_line);
        keyboard_task = launch_keyboard( );

        if (sic_get_task_id(keyboard_task) == sic_get_task_id(_sic_task_null)) {
            *code = -1;
            return;
        }

    }
}

static sic_command_from_t s_from = SIC_KEYBOARD;

static void redraw_prompt_c( char *prompt, char *line, int code)
{
    command_line_t command_line;

    strcpy( command_line.prompt, prompt);
    if (code)
        strcpy( command_line.line, line);
    else
        command_line.line[0] = '\0';
    command_line.nc = strlen( command_line.line);
    command_line.code = code;
    if (s_from == SIC_KEYBOARD || s_from == SIC_SYNCHRONOUS_MODE) {
        sic_post_prompt( &command_line);
    } else if (s_from != SIC_SILENT_MODE) {
        sic_fire_redraw_prompt_event( &command_line);
    }
}

static void redraw_prompt( CFC_FzString prompt, CFC_FzString line, int code)
{
    redraw_prompt_c( CFC_fz2c_string( prompt), CFC_fz2c_string( line), code);
}

/*********************************************************************
  First send the result of last executed command to the keyboard
  manager program.
  Then block on semaphore and read the command to be executed in shared memory
  at the reception of a signal form X-Window Application or at semaphore
  released by the keyboard manager program.
  ********************************************************************/
int CFC_API read_linec( CFC_FzString prompt, CFC_FzString line, int *code, int *wait_command)
{
    command_line_t command_line;

    redraw_prompt( prompt, line, *code);

    if (timerstatus)
        set_timer( timervalue);

    do {
        sic_wait_command( &command_line, &s_from);
    } while (!*wait_command && s_from != SIC_KEYBOARD);

    sic_suspend_prompt( s_from);

    if (timerstatus)
        set_timer( 1000000);

    CFC_c2fz_strcpy( prompt, command_line.prompt);
    CFC_c2fz_strcpy( line, command_line.line);
    *code = command_line.code;
    return (int)command_line.nc;
}

