/*
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#ifdef HAVE_MEMORY_H
#include <memory.h>
#endif
#include <stdio.h>
#ifdef HAVE_STRING_H
#include <string.h>
#endif

#include <glib.h>
#include <gdk/gdk.h>
#include <gtk/gtk.h>
#include <pango/pango-font.h>

#include <libxfce4util/libxfce4util.h>

static const char *states[] = {
    "normal", "active", "prelight", "selected", "insensitive", NULL
};

static const char *names[] = {
    "fg", "bg", "text", "base", "light", "dark", "mid", NULL
};

#define GTKSTYLE_FG    0
#define GTKSTYLE_BG    1
#define GTKSTYLE_TEXT  2
#define GTKSTYLE_BASE  3
#define GTKSTYLE_LIGHT 4
#define GTKSTYLE_DARK  5
#define GTKSTYLE_MID   6

static gint
state_value (const gchar * s)
{
    const gchar *t;
    gint u;

    t = states[0];
    u = 0;

    while ((states[u]) && (strcmp (states[u], s)))
    {
	u++;
    }
    if (states[u])
    {
	return (u);
    }
    return (0);
}

static gint
name_value (const gchar * s)
{
    const gchar *t;
    gint u;

    t = names[0];
    u = 0;

    while ((names[u]) && (strcmp (names[u], s)))
    {
	u++;
    }
    if (names[u])
    {
	return (u);
    }
    return (0);
}

static gchar *
print_color (GtkWidget * win, GdkColor * c)
{
    gchar *s;
    GdkColor real_color;
    GdkColormap *cmap;

    s = g_new (gchar, 14);
    cmap = gtk_widget_get_colormap (GTK_WIDGET (win));
    if (cmap && GDK_IS_COLORMAP (cmap))
    {
	gdk_colormap_query_color (cmap, c->pixel, &real_color);
	g_snprintf (s, 14, "#%04x%04x%04x", real_color.red, real_color.green,
		    real_color.blue);
    }
    else
    {
	g_snprintf (s, 14, "#%04x%04x%04x", c->red, c->green, c->blue);
    }
    return (s);
}

static gchar *
print_colors (GtkWidget * win, GdkColor * x, int n)
{
    return (print_color (win, x + n));
}

static gchar *
print_rc_style (GtkWidget * win, const gchar * name, const gchar * state,
		GtkStyle * style)
{
    gchar *s;
    gint n, m;
    g_return_val_if_fail (state != NULL, NULL);
    g_return_val_if_fail (name != NULL, NULL);

    n = state_value (state);
    m = name_value (name);

    switch (m)
    {
	case GTKSTYLE_FG:
	    s = print_colors (win, style->fg, n);
	    break;
	case GTKSTYLE_BG:
	    s = print_colors (win, style->bg, n);
	    break;
	case GTKSTYLE_TEXT:
	    s = print_colors (win, style->text, n);
	    break;
	case GTKSTYLE_BASE:
	    s = print_colors (win, style->base, n);
	    break;
	case GTKSTYLE_LIGHT:
	    s = print_colors (win, style->light, n);
	    break;
	case GTKSTYLE_DARK:
	    s = print_colors (win, style->dark, n);
	    break;
	default:
	case GTKSTYLE_MID:
	    s = print_colors (win, style->mid, n);
	    break;
    }
    return (s);
}

gchar *
get_style (GtkWidget * win, const gchar * name, const gchar * state)
{
    GtkStyle *style = NULL;
    gchar *s = NULL;

    TRACE ("entering get_style");

    g_return_val_if_fail (win != NULL, NULL);
    g_return_val_if_fail (GTK_IS_WIDGET (win), NULL);
    g_return_val_if_fail (GTK_WIDGET_REALIZED (win), NULL);

    style = gtk_rc_get_style (win);
    if (!style)
    {
	style = gtk_widget_get_style (win);
    }
    s = print_rc_style (win, name, state, style);
    TRACE ("%s[%s]=%s", name, state, s);
    return (s);
}

static GdkGC *
_get_style_gc (const gchar * name, const gchar * state, GtkStyle * style)
{
    GdkGC *gc = NULL;
    gint n, m;

    g_return_val_if_fail (state != NULL, NULL);
    g_return_val_if_fail (name != NULL, NULL);
    g_return_val_if_fail (style != NULL, NULL);
    g_return_val_if_fail (GTK_IS_STYLE(style), NULL);

    n = state_value (state);
    m = name_value (name);

    switch (m)
    {
	case GTKSTYLE_FG:
	    gc = style->fg_gc[n];
	    break;
	case GTKSTYLE_BG:
	    gc = style->bg_gc[n];
	    break;
	case GTKSTYLE_TEXT:
	    gc = style->text_gc[n];
	    break;
	case GTKSTYLE_BASE:
	    gc = style->base_gc[n];
	    break;
	case GTKSTYLE_LIGHT:
	    gc = style->light_gc[n];
	    break;
	case GTKSTYLE_DARK:
	    gc = style->dark_gc[n];
	    break;
	default:
	case GTKSTYLE_MID:
	    gc = style->mid_gc[n];
	    break;
    }
    
    return (gc);
}

GdkGC *
get_style_gc (GtkWidget * win, const gchar * name, const gchar * state)
{
    GtkStyle *style = NULL;

    TRACE ("entering get_style_gc");

    g_return_val_if_fail (win != NULL, NULL);
    g_return_val_if_fail (GTK_IS_WIDGET (win), NULL);
    g_return_val_if_fail (GTK_WIDGET_REALIZED (win), NULL);

    style = gtk_rc_get_style (win);
    if (!style)
    {
	style = gtk_widget_get_style (win);
    }
    if (!style)
    {
	style = gtk_widget_get_default_style ();
    }
    return (_get_style_gc (name, state, style));
}

PangoFontDescription *
get_font_desc (GtkWidget * win)
{
    TRACE ("entering get_font_desc");

    g_return_val_if_fail (win != NULL, NULL);
    g_return_val_if_fail (GTK_IS_WIDGET (win), NULL);
    g_return_val_if_fail (GTK_WIDGET_REALIZED (win), NULL);

    return (win->style->font_desc);
}

PangoContext *
pango_get_context (GtkWidget * win)
{
    TRACE ("entering pango_get_context");

    g_return_val_if_fail (win != NULL, NULL);
    g_return_val_if_fail (GTK_IS_WIDGET (win), NULL);
    g_return_val_if_fail (GTK_WIDGET_REALIZED (win), NULL);

    return (gtk_widget_get_pango_context (win));
}
