#include "rugby-cell-renderer-score.h"
#include "rugby-scoring.h"

enum
{
	PROP_0,
	PROP_TRIES,
	PROP_UTRIES,
	PROP_PENS
};

struct _RugbyCellRendererScorePrivate
{
	gint tries;
	gint utries;
	gint pens;
};

/* Style classes for the different types of score */
#define RUGBY_STYLE_CLASS_TRY "try"
#define RUGBY_STYLE_CLASS_UTRY "utry"
#define RUGBY_STYLE_CLASS_PEN "pen"

G_DEFINE_TYPE (RugbyCellRendererScore, rugby_cell_renderer_score, GTK_TYPE_CELL_RENDERER)

static void
rugby_cell_renderer_score_set_property (GObject      *object,
                                        guint         prop_id,
                                        const GValue *value,
                                        GParamSpec   *pspec)
{
	RugbyCellRendererScorePrivate *priv = RUGBY_CELL_RENDERER_SCORE (object)->priv;

	switch (prop_id)
	{
		case PROP_TRIES:
			priv->tries = g_value_get_int (value);
			break;
		case PROP_UTRIES:
			priv->utries = g_value_get_int (value);
			break;
		case PROP_PENS:
			priv->pens = g_value_get_int (value);
			break;
		default:
			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
			break;
	}
}

static void
rugby_cell_renderer_score_get_property (GObject    *object,
                                        guint       prop_id,
                                        GValue     *value,
                                        GParamSpec *pspec)
{
	RugbyCellRendererScorePrivate *priv = RUGBY_CELL_RENDERER_SCORE (object)->priv;

	switch (prop_id)
	{
		case PROP_TRIES:
			g_value_set_int (value, priv->tries);
			break;
		case PROP_UTRIES:
			g_value_set_int (value, priv->utries);
			break;
		case PROP_PENS:
			g_value_set_int (value, priv->pens);
			break;
		default:
			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
			break;
	}
}

#define FIXED_WIDTH 400
#define FIXED_HEIGHT 20

static void
rugby_cell_renderer_score_get_preferred_width (GtkCellRenderer *cell,
                                               GtkWidget       *widget,
                                               gint            *minimum_width,
                                               gint            *natural_width)
{
	gint xpad;
	gint width;

	gtk_cell_renderer_get_padding (cell, &xpad, NULL);
	width = xpad * 2 + FIXED_WIDTH;

	if (minimum_width)
		*minimum_width = width;
	if (natural_width)
		*natural_width = width;
}

static void
rugby_cell_renderer_score_get_preferred_height (GtkCellRenderer *cell,
                                                GtkWidget       *widget,
                                                gint            *minimum_height,
                                                gint            *natural_height)
{
	gint ypad;
	gint height;

	gtk_cell_renderer_get_padding (cell, NULL, &ypad);
	height = ypad * 2 + FIXED_HEIGHT;

	if (minimum_height)
		*minimum_height = height;
	if (natural_height)
		*natural_height = height;
}

static void
render_bar (GtkStyleContext *context,
            cairo_t         *cr,
            gdouble          x,
            gdouble          y,
            gdouble          width,
            gdouble          height,
            RugbyScoreType   type)
{
	gtk_style_context_save (context);

	switch (type)
	{
		case RUGBY_SCORE_TYPE_TRY:
			gtk_style_context_add_class (context, RUGBY_STYLE_CLASS_TRY);
			break;
		case RUGBY_SCORE_TYPE_UTRY:
			gtk_style_context_add_class (context, RUGBY_STYLE_CLASS_UTRY);
			break;
		case RUGBY_SCORE_TYPE_PEN:
			gtk_style_context_add_class (context, RUGBY_STYLE_CLASS_PEN);
			break;
	}

	gtk_render_activity (context, cr, x, y, width, height);

	gtk_style_context_restore (context);
}

static void
rugby_cell_renderer_score_render (GtkCellRenderer      *cell,
                                  cairo_t              *cr,
                                  GtkWidget            *widget,
                                  const GdkRectangle   *background_area,
                                  const GdkRectangle   *cell_area,
                                  GtkCellRendererState  flags)
{
	RugbyCellRendererScorePrivate *priv = RUGBY_CELL_RENDERER_SCORE (cell)->priv;
	GtkStyleContext *context;
	gint xpad, ypad;
	gdouble x, y, total_w, w, h;
	GtkBorder padding, border;
	gint tries, utries, pens;
	gint total;
	gint i;

	context = gtk_widget_get_style_context (widget);

	gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
	x = cell_area->x + xpad;
	y = cell_area->y + ypad;
	total_w = cell_area->width - xpad * 2;
	h = cell_area->height - ypad * 2;

	gtk_style_context_save (context);
	gtk_style_context_add_class (context, GTK_STYLE_CLASS_TROUGH);

	gtk_render_background (context, cr, x, y, total_w, h);
	gtk_render_frame (context, cr, x, y, total_w, h);

	gtk_style_context_get_border (context, GTK_STATE_FLAG_NORMAL, &border);
	gtk_style_context_get_padding (context, GTK_STATE_FLAG_NORMAL, &padding);

	x += border.left + padding.left;
	y += border.top + padding.top;
	total_w -= border.left + border.right + padding.left + padding.right;
	h -= border.top + border.bottom + padding.top + padding.bottom;

	gtk_style_context_restore (context);

	tries = priv->tries;
	utries = priv->utries;
	pens = priv->pens;
	total = tries * TRY_POINTS + utries * UTRY_POINTS + pens * PEN_POINTS;

	gtk_style_context_save (context);
	gtk_style_context_add_class (context, GTK_STYLE_CLASS_PROGRESSBAR);

	w = total_w / (total / 7.0);
	for (i = 0; i < tries; i++)
	{
		render_bar (context, cr, x, y, w, h, RUGBY_SCORE_TYPE_TRY);
		x += w;
	}

	w = total_w / (total / 5.0);
	for (i = 0; i < utries; i++)
	{
		render_bar (context, cr, x, y, w, h, RUGBY_SCORE_TYPE_UTRY);
		x += w;
	}

	w = total_w / (total / 3.0);
	for (i = 0; i < pens; i++)
	{
		render_bar (context, cr, x, y, w, h, RUGBY_SCORE_TYPE_PEN);
		x += w;
	}

	gtk_style_context_restore (context);
}

static void
rugby_cell_renderer_score_class_init (RugbyCellRendererScoreClass *klass)
{
	GObjectClass *obj_class = G_OBJECT_CLASS (klass);
	GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (klass);

	obj_class->get_property = rugby_cell_renderer_score_get_property;
	obj_class->set_property = rugby_cell_renderer_score_set_property;

	cell_class->get_preferred_width = rugby_cell_renderer_score_get_preferred_width;
	cell_class->get_preferred_height = rugby_cell_renderer_score_get_preferred_height;
	cell_class->render = rugby_cell_renderer_score_render;

	g_object_class_install_property (obj_class, PROP_TRIES,
	                                 g_param_spec_int ("tries", "Tries", "Number of tries",
	                                                   0, 50, 0,
	                                                   G_PARAM_READWRITE));

	g_object_class_install_property (obj_class, PROP_UTRIES,
	                                 g_param_spec_int ("utries", "Unconverted Tries", "Number of Unconverted Tries",
	                                                   0, 50, 0,
	                                                   G_PARAM_READWRITE));

	g_object_class_install_property (obj_class, PROP_PENS,
	                                 g_param_spec_int ("pens", "Penalties", "Number of penalties",
	                                                   0, 50, 0,
	                                                   G_PARAM_READWRITE));

	g_type_class_add_private (klass, sizeof (RugbyCellRendererScorePrivate));
}

static void
rugby_cell_renderer_score_init (RugbyCellRendererScore *cellscore)
{
	RugbyCellRendererScorePrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE ((cellscore), RUGBY_TYPE_CELL_RENDERER_SCORE, RugbyCellRendererScorePrivate);

	priv->tries = 0;
	priv->utries = 0;
	priv->pens = 0;

	gtk_cell_renderer_set_padding (GTK_CELL_RENDERER (cellscore), 2, 2);

	cellscore->priv = priv;
}

GtkCellRenderer *
rugby_cell_renderer_score_new (void)
{
	return g_object_new (RUGBY_TYPE_CELL_RENDERER_SCORE, NULL);
}