/***************************** LICENSE START ***********************************

 Copyright 2012 ECMWF and INPE. This software is distributed under the terms
 of the Apache License version 2.0. In applying this license, ECMWF does not
 waive the privileges and immunities granted to it by virtue of its status as
 an Intergovernmental Organization or submit itself to any jurisdiction.

 ***************************** LICENSE END *************************************/

#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include <X11/IntrinsicP.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/CoreP.h>
#include <X11/cursorfont.h>
#include "LED.h"
#include "LEDP.h"
#include <Xm/ManagerP.h>


#ifndef ABS
#define ABS(a)           ((a)>=0?(a):-(a))
#endif
#ifndef MIN
#define MIN(a,b)         ((a)>(b)?(b):(a))
#endif

static void    create_gcs();
static void    calc_new_size();

static void draw(LEDWidget w);
/*
  Widget class methods
*/

static void    Initialize();
static void    Redisplay();
static void    Resize();
static void    Destroy();
static void    Activate();
static Boolean SetValues();

static void time_out(LEDWidget w,XtIntervalId id);

static XtResource resources[] = {
     {"color1", "Color1", XtRPixel, sizeof (Pixel),
    XtOffset(LEDWidget, led.color1), XtRString,"yellow"},

	     {"color2", "Color2", XtRPixel, sizeof (Pixel),
    XtOffset(LEDWidget, led.color2), XtRString,"white"},

	     {"color3", "Color3", XtRPixel, sizeof (Pixel),
    XtOffset(LEDWidget, led.color3), XtRString,"#404040404040"},

	{"blinkRate", "BlinkRate", XtRInt, sizeof (int),
	XtOffset(LEDWidget, led.timeout), XtRImmediate,(XtPointer)500},

};

/*---------------------------------------------------------------*/
/* Static initialisation of the class record                     */
/*---------------------------------------------------------------*/

LEDClassRec  ledClassRec = {
	{
	(WidgetClass) &xmPrimitiveClassRec,  /* superclass            */
	"LED",                            /* class_name            */
	sizeof(LEDRec),                   /* widget_size           */
	NULL,                                /* class_initialize      */
	NULL,                                /* class_part_initialize */
	FALSE,                               /* class_inited          */
	Initialize,                          /* initialize            */
	NULL,                                /* initialize_hook       */
	XtInheritRealize,                    /* realize               */
	NULL,                                /* actions               */
	0,                                   /* num_actions           */
	resources,                           /* resources             */
	XtNumber(resources),                 /* num_resources         */
	NULLQUARK,                           /* xrm_class             */
	TRUE,                                /* compress_motion       */
	TRUE,                                /* compress_exposure     */
	TRUE,                                /* compress_enterleave   */
	TRUE,                                /* visible_interest      */
	Destroy,                             /* destroy               */
	Resize,                              /* resize                */
	Redisplay,                           /* expose                */
	SetValues,                           /* set_values            */
	NULL,                                /* set_values_hook       */
	XtInheritSetValuesAlmost,            /* set_values_almost     */
	NULL,                                /* get_values_hook       */
	NULL,                                /* accept_focus          */
	XtVersion,                           /* version               */
	NULL,                                /* callback private      */
	XtInheritTranslations,                 /* tm_table              */
	NULL,                                /* query_geometry        */
	NULL,                                /* display_accelerator   */
	NULL,                                /* extension             */
	},
	{
	(XtWidgetProc)_XtInherit,             /* border_highlight      */
	(XtWidgetProc)_XtInherit,             /* border_unhighligh     */
	XtInheritTranslations,                /* translations          */
	(XtActionProc)_XtInherit,             /* arm_and_activate      */
	NULL,                                 /* syn_resources         */
	0,                                    /* num_syn_resources     */
	NULL,                                 /* extension             */
	},
	{
	0,                                    /* ignore                */
	},
};

WidgetClass ledWidgetClass = (WidgetClass) &ledClassRec;

/*---------------------------------------------------------------*/
/* Create the two GCs needed                                     */
/*---------------------------------------------------------------*/

static void create_gcs(LEDWidget w)
{
	XGCValues values;
	XtGCMask  valueMask;

	valueMask         =  GCFunction | GCForeground;
	values.function   = GXcopy;

	values.foreground = w->led.color1;
	w->led.gc1 = XtGetGC((Widget)w,valueMask,&values);

	values.foreground = w->led.color2;
	w->led.gc2 = XtGetGC((Widget)w,valueMask,&values);

	values.foreground = w->led.color3;
	w->led.gc3 = XtGetGC((Widget)w,valueMask,&values);

}

static void free_gcs(LEDWidget w)
{
	XtReleaseGC((Widget)w,w->led.gc1);
	XtReleaseGC((Widget)w,w->led.gc2);
	XtReleaseGC((Widget)w,w->led.gc3);
}

/*--------------------------------------------------------------*/
/* Initialize: Create the GCs                                   */
/*--------------------------------------------------------------*/

static void start(LEDWidget w)
{
	time_out(w,0);
}

static void stop(LEDWidget w)
{
	if(w->led.timeout_id)
		XtRemoveTimeOut(w->led.timeout_id);
	if(w->led.state)
	{
		w->led.state = False;
		if(XtIsRealized(w)) draw(w);
	}
}

static void Initialize (LEDWidget request, LEDWidget new)
{
	/* Check the size of the widget */

	if (request->core.width == 0)
		new->core.width = 24;

	if (request->core.height == 0)
		new->core.height = 6;

	request->led.on         = False;
	request->led.state      = False;
	request->led.timeout_id = 0;

	create_gcs(new);

	start(new);

}



/*--------------------------------------------------------------*/
/* Destroy the widget: release all memory alocated              */
/*--------------------------------------------------------------*/

static void Destroy (LEDWidget w)
{
	stop(w);
	free_gcs(w);
}


static void Resize (LEDWidget w)
{
}

static void draw(LEDWidget w)
{

	int n;

	if(w->led.state)
	{
			 XFillRectangle(XtDisplay(w),XtWindow(w),
			 	w->led.gc2,
				1,1,
				w->core.width-2,
				w->core.height-2);
	}
	else
	{
			 XFillRectangle(XtDisplay(w),XtWindow(w),
			 	XmParentBackgroundGC(w),
				1,1,
				w->core.width-2,
				w->core.height-2);

	}


	XDrawLine(XtDisplay(w),XtWindow(w),
		w->led.gc1,
		2,
		w->core.height-2,
		w->core.width-2,
		w->core.height-2);

	n = w->core.width-2;
	while(n >= 2)
	{
		XDrawLine(XtDisplay(w),XtWindow(w),
			w->led.gc1,
			n,
			2,
			n,
			w->core.height-2);
		n -= 2;
	}


	if(!w->led.state)
	{
			XDrawLine(XtDisplay(w),XtWindow(w),
				w->led.gc3,
				2,
				w->core.height-2,
				w->core.width-2,
				w->core.height-2);

			XDrawLine(XtDisplay(w),XtWindow(w),
				w->led.gc3,
				w->core.width-2,
				2,
				w->core.width-2,
				w->core.height-2);


	}

	_XmDrawShadows(XtDisplay(w), XtWindow(w),
	    XmParentTopShadowGC(w),
	    XmParentBottomShadowGC(w),
		0,
		0,
		w->core.width ,
		w->core.height,
		1,
	    XmSHADOW_IN);
}

static void Redisplay(LEDWidget w, XEvent *event, Region region)
{
	draw(w);
}

static void time_out(LEDWidget w,XtIntervalId id)
{
	if(XtIsRealized(w))
	{
		w->led.state = !w->led.state;	
		draw(w);
	}
	w->led.timeout_id = XtAppAddTimeOut(
			XtWidgetToApplicationContext((Widget)w),
			w->led.timeout, (XtTimerCallbackProc)time_out,
			(XtPointer)w);
}

/*------------------------------------------------------------------*/
/* SetValues : redraw only for font or color changes                */
/*------------------------------------------------------------------*/

static Boolean SetValues (LEDWidget current, LEDWidget request, 
LEDWidget new)
{
	Boolean    redraw = FALSE;
	redraw = True;
	return (redraw);
}


/*-----------------------------------------------------------------------*/
/* Create a new LEDWidget                                              */
/*-----------------------------------------------------------------------*/

Widget CreateLEDWidget(Widget parent,char *name,Arg *al,int ac)
{
	return XtCreateWidget(name,ledWidgetClass,parent,al,ac);
}

void LEDSwitch(Widget w,Boolean onOff)
{
	LEDWidget cw = (LEDWidget)w;
	if(onOff)
	{
		cw->led.speed++;
	}
	else
	{
		cw->led.speed--;
	}

}
