
/*
 * Desktop time client
 * (C) Joseph Heenan, 1997-9
 *
 * $Id: main,v 1.6 1999/10/16 14:38:33 joseph Exp $
 *
 */

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

#include "defines.h"

#include "kernel.h"

#include "swis.h"
#include "wimp.h"
#include "wimplib.h"
#include "wimpclib.h"

#include "rdate.h"
#include "config.h"

#define WimpVersion 310

static int wimp_messages [] = {
       Wimp_MOpenUrl,
       Wimp_MDataOpen,
       URI_MReturnResult,
       /* Wimp_MQuit is implicit, zero on it's own mean all messages */
       0};

const char frontend_taskname[] = TASK_NAME;

static int pollmask = (
/*     	   	        Wimp_Poll_NullMask | */
/*                      Wimp_Poll_RedrawWindowRequestMask | */
                      Wimp_Poll_PointerLeavingWindowMask |
                      Wimp_Poll_PointerEnteringWindowMask |
/*                      Wimp_Poll_MouseClickMask | */
                      Wimp_Poll_KeyPressedMask |
                      Wimp_Poll_LoseCaretMask |
                      Wimp_Poll_GainCaretMask |
                      Wimp_Poll_PollWordNonZeroMask |
/*                      Wimp_Poll_UserMessageMask | */
/*                      Wimp_Poll_UserMessageRecordedMask | */
/*                      Wimp_Poll_UserMessageAcknowledgeMask | */
/*                      Wimp_Poll_PollWord | */
/*                      Wimp_Poll_PollWordHighPriority | */
/*                      Wimp_Poll_SaveFPRegs | */
                      0);

static int     quit = 0;
static int      frontend_mainwindow = 0;
static int      frontend_infowin = 0;
static WimpMenu *frontend_mainmenu = NULL;
static time_t  stoptime;
static char    error[512];
static int     retries = 0; /* How many times we've retried so far */
static enum    { WORKING, DONE, WAITING, RETRY}
               state = WORKING; /* working = getting time, retry = waiting after a dns failure
       			      	 * done = displaying window, waiting = asking user */

#define INFOWIN_AUTHOR        2
#define INFOWIN_WEBSITE       8
#define INFOWIN_VERSION       3

#define MAINMENU ">Info,Help...,Configure...,Quit", \
                 frontend_infowin

enum
{
  MAINMENU_INFO,
  MAINMENU_HELP,
  MAINMENU_CONFIGURE,
  MAINMENU_QUIT
};


static void working(void);
static void window_movewindow(int handle);
static void frontend_mouseclick( int window, int icon, int but, int x, int y );
static int key_alt( void );
static void frontend_menuselection(WimpMenuSelections sel, int adjust);

int main( int argc, char *argv[] )
{
  WimpPollBlock pollblock;
  _kernel_oserror *e;
  int reason;

  if ( key_alt() )
  {
    _swix(OS_CLI, _IN(0), "Filer_Run <FreeTime$Dir>.!FTsetup" );
    exit( EXIT_SUCCESS );
  }

  if ( wimpc_taskpresent(TASK_NAME) )
    exit( EXIT_SUCCESS );

  e=wimp_initialise(WimpVersion,TASK_NAME,wimp_messages,NULL /* wimp version*/ ,NULL /* task handle */);
  E_CHECK_ABORT(e);

  e = wimp_open_template(TASK_DIR".Templates");
  E_CHECK_ABORT(e);

  frontend_mainwindow = wimpc_loadtemplate( "status" );
  frontend_infowin = wimpc_loadtemplate( "info" );
  if ( frontend_mainwindow == -1 || frontend_infowin == -1 )
  {
    wimp_close_template();
    exit(1);
  }

  e = wimp_close_template();
  E_CHECK_ABORT(e);

  frontend_mainmenu = wimpc_createmenu( 0, ',', TASK_NAME, MAINMENU );
  if ( !frontend_mainmenu )
  {
    E_REPORT("Out of memory, could not create main menu!\n");
    exit( 1 );
  }

  rdate_main( error, argc, argv ); // read config file
  wimpc_seticontext( frontend_mainwindow, 1, "Getting time from server" );
  {
    char text[16];
    *text=0;
    strncat(text,TASK_NAME, sizeof(text)-1);
    strncat(text," v", sizeof(text)-(strlen(text)+1) );
    strncat(text,TASK_VERSION, sizeof(text)-(strlen(text)+1) );
    wimpc_seticontext(frontend_mainwindow, 3, text);
  }

  wimpc_setinfoversion( frontend_infowin, INFOWIN_VERSION, TASK_VERSION, __DATE__ );

  if ((config_windowdisplay & 1)==1)
    wimpc_openwindowcentre( frontend_mainwindow, 0 );

  while (!quit)
  {
    if (state==WORKING)
      e = wimp_poll (pollmask, &pollblock, NULL, &reason);
    else
    {
      unsigned int time;
      _swix(OS_ReadMonotonicTime, _OUT(0),&time);
      e = wimp_pollidle(pollmask, &pollblock, time+100, NULL, &reason);
    }

    E_CHECK(e);
    switch (reason)
    {
      case Wimp_ENull:
        switch (state)
        {
          case WORKING:
            working();
            break;
          case RETRY:
            if ( (time(NULL)-stoptime) > config_retrydelay )
              state=WORKING;
            break;
          case DONE:
            if ( config_windowdelay != 0 )
              if ( (time(NULL)-stoptime) > config_windowdelay )
                quit=1;
            break;
          case WAITING:
            if ( (time(NULL)-stoptime) > (5*60) )
              quit=1;
            break;
        }
        break;


      case Wimp_EOpenWindow:
        wimp_open_window((WimpOpenWindowBlock *)&pollblock);
        break;

      case Wimp_ERedrawWindow:
        break;

      case Wimp_ECloseWindow:
        if (pollblock.close_window_request.window_handle==frontend_mainwindow)
          quit=1;
        break;

      case Wimp_EMouseClick:
        frontend_mouseclick( pollblock.mouse_click.window_handle, pollblock.mouse_click.icon_handle,
                             pollblock.mouse_click.buttons,       pollblock.mouse_click.mouse_x,
                             pollblock.mouse_click.mouse_y);
        break;

      case Wimp_EMenuSelection:
      {
        WimpGetPointerInfoBlock pointer;
        wimp_get_pointer_info( &pointer );
        frontend_menuselection( pollblock.menu_selection, pointer.button_state & Wimp_MouseButtonAdjust );
      } break;

      case Wimp_EUserMessageRecorded:
        if ( pollblock.user_message.hdr.action_code == URI_MReturnResult )
          url_bounce( &pollblock.user_message );

      case Wimp_EUserMessage:
        switch(pollblock.user_message.hdr.action_code)
        {
          case Wimp_MQuit:
            quit = 1;
            break;

          case Wimp_MDataOpen:
          {
            WimpDataOpen *open = &pollblock.user_message.data.data_open;
            char *ptr, *x;
            static char leafname[20] = "";
            if ( open->file_type != 0x2000 )
              break;
            /* it's an application click. find out our pathname */
            if ( !*leafname )
            {
              ptr = getenv( "FreeTime$Dir" );
              if ( !ptr ) break;
              /* get the leafname */
              x = strrchr( ptr, '.' );
              if ( !x ) break;
              x++;
              strncat( leafname, x, sizeof(leafname) - 1 );
            }
            ptr = open->path_name + strlen( open->path_name ) - strlen( leafname );
            if ( strcmp( ptr, leafname ) )
              break;
            /* Okay, it's us and it's an application. */
            wimpc_openwindowcentre( frontend_mainwindow, 0 );
          } break;

        }
        break;

        case Wimp_EUserMessageAcknowledge:
          if ( pollblock.user_message.hdr.action_code == Wimp_MOpenUrl )
            url_bounce( &pollblock.user_message );
          break;

    }
  }

  rdate_abort();

  return EXIT_SUCCESS;
}

static void frontend_menuselection(WimpMenuSelections sel, int adjust)
{
  switch ( sel[0] )
  {
    case MAINMENU_INFO:
      break;

    case MAINMENU_HELP:
      {
        static const char show_help_cmd[] = "Filer_Run <FreeTime$Dir>.!Help";
        _swix(OS_CLI, _IN(0), show_help_cmd);
      }
      break;

    case MAINMENU_CONFIGURE:
      {
        static const char show_help_cmd[] = "Filer_Run <FreeTime$Dir>.!FTsetup";
        _swix(OS_CLI, _IN(0), show_help_cmd);
      }
      break;

    case MAINMENU_QUIT:
      quit = 1;
      break;
  }
  if (adjust)
    E_CHECK( wimp_create_menu(frontend_mainmenu, 0, 0)); /* redisplay menu */
}


static void frontend_mouseclick( int window, int icon, int but, int x, int y )
{
  if (window == frontend_infowin)
  {
    switch (icon)
    {
      case INFOWIN_AUTHOR:
        url_launch("mailto:joseph@ping.demon.co.uk");
        break;
      case INFOWIN_WEBSITE:
        url_launch("http://www.ping.demon.co.uk/acorn/download.html");
        break;
    }
    return;
  }
  else if (window == frontend_mainwindow)
  {
    if (but & Wimp_MouseButtonMenu)
    {
      E_CHECK(wimp_create_menu(frontend_mainmenu, x-64, y));
    }
    else if (icon == 6)
    {
      static const char show_help_cmd[] = "Filer_Run <FreeTime$Dir>.!Help";
      _swix(OS_CLI, _IN(0), show_help_cmd);
    }
    else if (state == DONE)
    {
      quit = 1;
    }
    else if (state == WAITING)
    {
      switch (icon)
      {
        case 4:
          rdate_settime();
          quit = 1;
          break;

        case 5:
          quit = 1;
          break;

        default:
          window_movewindow(frontend_mainwindow);
      }
    }
    else if ( state == RETRY || state == WORKING )
    {
      window_movewindow(frontend_mainwindow);
    }
  }
}

static void window_movewindow(int handle)
{
  _kernel_oserror *e;
  WimpDragBox block;
  WimpGetWindowStateBlock state;

  state.window_handle = handle;
  e=wimp_get_window_state(&state); E_CHECK(e);

  block.wimp_window  = handle;
  block.drag_type    = Wimp_DragBox_DragWindow;
  block.dragging_box = state.visible_area;

  e=wimp_drag_box(&block); E_CHECK(e);
}


static int key_alt( void )
{
  int state;
  if ( _swix( OS_Byte, _INR(0,2) | _OUT(1), 202, 0, 255, &state ) ) return 0;
  return state & 1;
}

static void working(void)
{
  int ret, win = 0;

  ret = rdate_main(error, 0, NULL);
  if (ret == 0) return; /* still working */

  if ( ret <= -100 && retries < config_retry )
  {
    /* could retry. */
    retries++;
    state=RETRY;
    stoptime=time(NULL);
    return;
  }

  wimpc_seticontext(frontend_mainwindow, 1, error); /* Place message rdate returned in window */

  state=DONE;
  stoptime=time(NULL);

  switch (ret)
  {
    case 1:
      if (config_windowdisplay & WINDOW_SHOWSET)
        win = 1;
      break;
    case 2:
      if (config_windowdisplay & WINDOW_SHOWMIN)
        win = 1;
      break;
    case 3:
      if (config_windowdisplay & WINDOW_SHOWOUT)
        win = 1;
      else
        rdate_settime();
      break;
    default:  if ( config_windowdisplay & WINDOW_SHOWERROR ) win = 1; break;
  }

  if (!win)
  {
    quit = 1;
    return;
  }

  if (ret == 3)
    state=WAITING; /* We need to query the user */

  wimpc_openwindowcentre(frontend_mainwindow, ret == 3); /* Display the results window, full size if necessary */
}
