/* Status in a Toolbox window
 *
 * $Id: status,v 1.16 2001/04/01 15:37:04 joseph Exp $
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include "memleak.h"
#include <string.h>

#include "wimplib.h"

#include "defines.h"

#include "config.h"
#include "dkm.h"
#include "err.h"
#include "log.h"
#include "status.h"
#include "stopquit.h"
#include "macros.h"
#include "IconNames.h"

#include "wimpclib.h"


struct status_info {
  int count;		/* Number of messages */
  int total;		/* Bytes in current msg */
  int abstotal;		/* Total number of bytes */
  int transferred;	/* Total transferred so far */
  int lasttrans;	/* Total transferred up to end of last message */
};


static status_handle saved_status_handle = NULL; /* used to prevent lots of malloc/free */


static void status_blank(status_handle h);


#ifndef FEATURE_NOSTATUS  
static int status_winhan = -1;
static int status_config;
static bool status_manual = false; /* whether or not the status window was opened by the user */
static void status_open(void);
#endif



status_handle status_create()
{
  static int firsttime = 1;
  status_handle h;

  if ( !saved_status_handle )
  {
    h = malloc(sizeof(struct status_info));
  }
  else
  {
    h = saved_status_handle;
    saved_status_handle = NULL;
  }

  if (!h)
    return 0;

  h->transferred = h->lasttrans = 0;

#ifndef FEATURE_NOSTATUS  
  status_config = config_lookup_num("AutoStatus");
  if (status_config == 2 || (status_config == 3 && firsttime))
    status_open();
#endif
  firsttime = 0;

  return h;
}


void status_free(status_handle h)
{
  status_blank(h);

#ifndef FEATURE_NOSTATUS  
  if (status_winhan != -1)
  {
    if (!status_manual)
      E(wimp_close_window( &status_winhan ));
  }
#endif

  if ( !saved_status_handle )
  {
    saved_status_handle = h;
  }
  else
  {
    free(h);
  }
}


#ifndef FEATURE_NOSTATUS


void status_close_handler( int winhan )
{
  if ( winhan == status_winhan )
    status_manual = false;
}

void status_init(int winhan)
{
  status_winhan = winhan;
}

/* returns :
 *   1 : click handle
 *   0 : not for us
 */
int status_click( int winhan, int icon, int but )
{
  if ( status_winhan != winhan ) return 0;

  if ( icon == status_GStop && but == Wimp_MouseButtonSelect )
    stopquit_handler( stopquit_Stop );

  return 1;
}

static void status_open(void)
{
  union
  {
    WimpGetWindowStateBlock state;
    WimpOpenWindowBlock     open;
  }
  block;
  if ( status_winhan == -1 ) return;

  block.state.window_handle = status_winhan;
  E_CHECK_RETURN( , wimp_get_window_state( &block.state ) );
  if ( config_lookup_bool( "BigStatus" ) )
  {
    WimpGetWindowInfoBlock info;
    info.window_handle = status_winhan;
    E_CHECK_RETURN( , wimp_get_window_info( (WimpGetWindowInfoBlock *) (((int)(&info))+1) ) );
    block.state.visible_area.xmin = block.state.visible_area.xmax -
    	(info.window_data.extent.xmax - info.window_data.extent.xmin);
    block.state.visible_area.ymin = block.state.visible_area.ymax -
    	(info.window_data.extent.ymax - info.window_data.extent.ymin);
    block.state.xscroll = block.state.yscroll = 0;
  }
  block.open.behind = -1;
  wimp_open_window( &block.open );
}

void status_openmanual(void)
{
  status_open();
  status_manual = true;
}


static void status_blank(status_handle h)
{
  h=h;

  if (status_winhan == -1)
    return;

  wimpc_seticontext( status_winhan, status_GUser,     "");
  wimpc_seticontext( status_winhan, status_GMsgBytes, "");
  wimpc_seticontext( status_winhan, status_GMsgCount, "");
  wimpc_seticontext( status_winhan, status_GTotal,    "");
}

void status_set_label(status_handle h, const char *msg)
{
  h=h;
                                    
  if ( status_winhan != -1 )
    wimpc_seticontext( status_winhan, status_GLabel, msg );
}

void status_show_misc(status_handle h, const char *msg)
{
  h=h;

  if ( status_winhan != -1 )
    wimpc_seticontext( status_winhan, status_GUser, msg );
}

void status_show_user(status_handle h, const char *name, const char *server)
{
  h=h;

  if (status_winhan != -1)
  {
    char msg[256];

    snprintf(msg, sizeof (msg), "%s@%s", name, server);
    wimpc_seticontext( status_winhan, status_GUser, msg );
  }
}

void status_bytes_total(status_handle h, int t)
{
  char msg[16] = "0/";

  if (h)
    h->total = t;
  if (status_winhan != -1)
  {

    dkm_to_str(msg + 2, t);
    wimpc_seticontext( status_winhan, status_GMsgBytes, msg );
  }
/*
  xsyslogf(log_NAME, log_DebugInfo, "Total bytes in message : %s (%d)", msg, t);
*/
}

void status_bytes(status_handle h, int n)
{
  if (h && status_winhan != -1)
  {
    char msg[16];
    int len;

    dkm_to_str(msg, n);
    if (h->total)
    {
      len = strlen(msg);
      msg[len] = '/';
      dkm_to_str(msg + len + 1, h->total);
    }
    wimpc_seticontext( status_winhan, status_GMsgBytes, msg );
    dkm_to_str(msg, h->transferred = h->lasttrans + n);
    len = strlen(msg);
    msg[len] = '/';
    dkm_to_str(msg + len + 1, h->abstotal);
    wimpc_seticontext( status_winhan, status_GTotal, msg );
  }
}

void status_total_total(status_handle h, int n)
{
  if (h)
  {
    h->abstotal = n;
    h->transferred = 0;
    h->lasttrans = 0;
  }
  if (status_winhan != -1)
  {
    char msg[16];

    dkm_to_str(msg, n);
    wimpc_seticontext( status_winhan, status_GTotal, msg );
  }
  /*xsyslogf(log_NAME, log_DebugInfo, "Total bytes in maildrop : %d", n);*/
}

void status_settitle( status_handle h, const char *title )
{
  h=h; /* unused */
  wimpc_settitle( status_winhan, title );
}

#else

#define FIELD_MAIL_STAT 5
#define FIELD_MAIL_PROG 6

#define FIELD_NEWS_STAT 7
#define FIELD_NEWS_PROG 8

#define MPRO_SET_STATUS 0x52580

typedef struct
{
  int    size;
  int    sender;
  int    my_ref;
  int    your_ref;
  int    action_code;
}
wimp_msg_header;

typedef struct
{
  wimp_msg_header hdr;
  
  struct
  {
    int    field_num;
    char   text[256 - 6 * 4];
  }
  data;
}
mpro_status_message;

static char status_title[64] = "";



static void status_sendmsg(int field_num, const char *text)
{
  mpro_status_message msg;
  int th;
  
  msg.hdr.size        = sizeof msg;
  msg.hdr.your_ref    = 0;
  msg.hdr.action_code = MPRO_SET_STATUS;

  msg.data.field_num  = field_num;
  msg.data.text[0]    = '\0';
  strncat(msg.data.text, text, sizeof(msg.data.text)-1);

  E_CHECK( wimp_send_message( Wimp_EUserMessage, &msg, 0, 0, &th) );
}


static void status_blank(status_handle h)
{
  h = h; /* unused */
  
  status_sendmsg(FIELD_MAIL_STAT, "");
  status_sendmsg(FIELD_MAIL_PROG, "");
}


void status_settitle( status_handle h, const char *title )
{
  h=h; /* unused */
  status_title[0] = '\0';
  strncat(status_title, title, sizeof(status_title) - 1);
}



void status_show_misc(status_handle h, const char *text)
{
  char msg[256];

  h=h; /* unused */
  
  snprintf(msg, sizeof (msg), "%s: %s", status_title, text);

  status_sendmsg( FIELD_MAIL_STAT, msg );
}



void status_show_user(status_handle h, const char *name, const char *server)
{
  char msg[256];
  
  h=h; /* unused */

  snprintf(msg, sizeof (msg), "%s: %s@%s", status_title, name, server);
  status_sendmsg( FIELD_MAIL_STAT, msg );
}


#endif


void status_count_total(status_handle h, int n)
{
  char msg[16];
  
  if (h)
    h->count = n;
  
  sprintf(msg, "0/%d", n);
  
#ifndef FEATURE_NOSTATUS
  if (status_winhan != -1)
  {
    wimpc_seticontext( status_winhan, status_GMsgCount, msg );
    if (n && (status_config == 1 || status_config == 3))
      status_open();
  }
#else
  status_sendmsg(FIELD_MAIL_PROG, msg);
#endif
}



void status_count(status_handle h, int m)
{
  if (h)
  {
    char msg[16];
    h->total = 0;
    h->lasttrans = h->transferred;
    sprintf(msg, "%d/%d", m, h->count);
#ifndef FEATURE_NOSTATUS
    if (status_winhan != -1)
      wimpc_seticontext( status_winhan, status_GMsgCount, msg );
#else
    status_sendmsg(FIELD_MAIL_PROG, msg);
#endif
  }
  /*xsyslogf(log_NAME, log_DebugInfo, "status_count : %d, h = %p, winhan", m, h, status_winhan);*/
}
