/*
 * Copyright (c) 2006 Alvaro Lopes <alvieboy@alvie.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "leds.h"

#ifdef BIG_LEGS
#include "big_leds.xpm"
#define LED_XPM big_leds_xpm
#else
#include "med_leds.xpm"
#define LED_XPM med_leds_xpm
#endif

#include <gdk-pixbuf/gdk-pixbuf.h>
#include "cellmodem.h"

static gboolean leds_initialized = FALSE;

static GdkPixbuf *whole_leds;
static GSList *flashing_leds;
static gint flash_timer;

#ifdef BIG_LEGS

static int led_h_size = 8;
static int led_v_size = 8;

#else

static int led_h_size = 6;
static int led_v_size = 6;

#endif


#define NUMBER_OF_LEDS 5

GdkPixbuf *pixleds[NUMBER_OF_LEDS];

static gboolean initialize_leds()
{
    int i;

    whole_leds = gdk_pixbuf_new_from_xpm_data( (const char**)LED_XPM );
    if (whole_leds == NULL)
	return FALSE;

    /* cut individual leds. */

    for (i=0; i<NUMBER_OF_LEDS; i++) {
	pixleds[i] =
	    gdk_pixbuf_new_subpixbuf( whole_leds,
				     i*led_h_size,
				     0,
				     led_h_size,
                                     led_v_size);
    }

    /* Initialize the list */

    flashing_leds = NULL;

    leds_initialized = TRUE;
    return TRUE;
}

static gboolean do_flash_leds( gpointer data )
{
    g_slist_foreach( flashing_leds,
		   (GFunc)led_t_flip_flash,
                   NULL );

    return TRUE;
}


void led_t_flip_flash( led_t *led, gpointer data )
{
    if ( ! led->flashing )
	return;

    led->flash_on = ~(led->flash_on);

    if ( led->flash_on ) {
	gtk_image_set_from_pixbuf( GTK_IMAGE(led->image), pixleds[ (int)led->color ]);
    } else {
	gtk_image_set_from_pixbuf( GTK_IMAGE(led->image), pixleds[ LED_OFF ]);
    }
}

led_t *led_t_new()
{
    led_t *led = g_new0( led_t, 1 );

    led->image = gtk_image_new();

    if ( leds_initialized == FALSE )
        initialize_leds();

    return led;
}

void led_t_set_color( led_t *led, led_color_t color )
{
    led->color = color;
    gtk_image_set_from_pixbuf( GTK_IMAGE(led->image), pixleds[ (int)color ]);
}


void led_t_set_flashing( led_t *led, gboolean flashing )
{
    if (  (led->flashing ^ flashing ) == 0 )
	return; /* Already in that state */

    led->flashing = flashing;

    if ( flashing )
    {
	/* Add to the list */

	flashing_leds = g_slist_append( flashing_leds,
				       ( gpointer ) led );

	if ( flash_timer <= 0 )
	{
	    flash_timer = g_timeout_add( 500,
					(GSourceFunc) do_flash_leds,
					NULL );
	}
    } else {
	flashing_leds = g_slist_remove( flashing_leds,
				       ( gconstpointer ) led );

	if (g_slist_length( flashing_leds ) == 0) {
            g_source_remove( flash_timer );
            flash_timer = -1;
	}
	gtk_image_set_from_pixbuf( GTK_IMAGE(led->image), pixleds[ (int)led->color ]);
    }

}


void  led_t_destroy( led_t *led )
{
    g_object_unref( G_OBJECT( led->image ) );
    /* Remove from flashing list */
    if (led->flashing) {
        led_t_set_flashing( led, FALSE );
    }
    g_free( led );
}

