/* rugby-score-store.c
 *
 * Copyright © 2012, 2016-2018 Bruce Cowan <bruce@bcowan.eu>
 *
 * This file is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 3 of the
 * License, or (at your option) any later version.
 *
 * This file 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "rugby-score-store.h"
#include "rugby-scoring.h"

enum
{
    FINISHED,
    LAST_SIGNAL
};

enum
{
    PROP_0,
    PROP_SCORE,
    PROP_LAST
};

static GParamSpec *pspecs[PROP_LAST];

struct _RugbyScoreStore
{
    GtkListStore parent_instance;

    gint score;
};

G_DEFINE_TYPE (RugbyScoreStore, rugby_score_store, GTK_TYPE_LIST_STORE)

static guint signals[LAST_SIGNAL] = { 0, };

static void
rugby_score_store_set_property (GObject      *object,
                                guint         prop_id,
                                const GValue *value,
                                GParamSpec   *pspec)
{
    RugbyScoreStore *self = RUGBY_SCORE_STORE (object);

    switch (prop_id)
    {
        case PROP_SCORE:
            rugby_score_store_set_score (self, g_value_get_int (value));
            break;
        default:
            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
            break;
    }
}

static void
rugby_score_store_get_property (GObject    *object,
                                guint       prop_id,
                                GValue     *value,
                                GParamSpec *pspec)
{
    RugbyScoreStore *self = RUGBY_SCORE_STORE (object);

    switch (prop_id)
    {
        case PROP_SCORE:
            g_value_set_int (value, rugby_score_store_get_score (self));
            break;
        default:
            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
            break;
    }
}

static void
rugby_score_store_class_init (RugbyScoreStoreClass *klass)
{
    GObjectClass *obj_class = G_OBJECT_CLASS (klass);

    obj_class->get_property = rugby_score_store_get_property;
    obj_class->set_property = rugby_score_store_set_property;

    pspecs[PROP_SCORE] = g_param_spec_int ("score", "Score", "The score",
                                           0, 200, 0,
                                           G_PARAM_READWRITE);
    g_object_class_install_property (obj_class, PROP_SCORE, pspecs[PROP_SCORE]);

    signals[FINISHED] =
        g_signal_new ("finished",
                      G_TYPE_FROM_CLASS (obj_class),
                      G_SIGNAL_RUN_LAST,
                      0,
                      NULL, NULL, NULL,
                      G_TYPE_NONE, 1,
                      G_TYPE_INT);
}

static void
populate_store_foreach (gpointer data,
                        gpointer user_data)
{
    RugbyPossibility *possiblity = (RugbyPossibility *) data;
    GtkListStore *store = GTK_LIST_STORE (user_data);

    GtkTreeIter iter;
    gint tries = possiblity->tries;
    gint utries = possiblity->utries;
    gint kicks = possiblity->kicks;

    g_autoptr (GString) string = g_string_new (NULL);

    if (tries > 0 || utries > 0)
        g_string_append_printf (string, "%d tries, %d converted",
                                tries + utries, tries);
    if (kicks > 0)
    {
        if (string->len == 0)
            g_string_append_printf (string, "%d kicks", kicks);
        else
            g_string_append_printf (string, ", %d kicks", kicks);
    }

    gtk_list_store_append (store, &iter);
    gtk_list_store_set (store, &iter,
                        RUGBY_SCORE_STORE_TRIES, tries,
                        RUGBY_SCORE_STORE_UTRIES, utries,
                        RUGBY_SCORE_STORE_KICKS, kicks,
                        RUGBY_SCORE_STORE_TOOLTIP, string->str,
                        -1);
}

static void
populate_store (RugbyScoreStore *self)
{
    GtkListStore *store = GTK_LIST_STORE (self);

    g_autoptr(GPtrArray) possibilities = NULL;

    /* Clear the store */
    gtk_list_store_clear (store);

    possibilities = rugby_scoring_get_possibilities (self->score);
    if (possibilities->len == 0)
        return;

    g_ptr_array_foreach (possibilities, populate_store_foreach, store);

    g_signal_emit (self, signals[FINISHED], 0, (gint) possibilities->len);
}

static void
rugby_score_store_init (RugbyScoreStore *self)
{
    GType types[] = { G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_STRING };

    gtk_list_store_set_column_types (GTK_LIST_STORE (self), RUGBY_SCORE_STORE_COLUMNS, types);
    self->score = 0;
}

RugbyScoreStore *
rugby_score_store_new (void)
{
    return g_object_new (RUGBY_TYPE_SCORE_STORE, NULL);
}

gint
rugby_score_store_get_score (RugbyScoreStore *self)
{
    g_return_val_if_fail (RUGBY_IS_SCORE_STORE (self), 0);

    return self->score;
}

void
rugby_score_store_set_score (RugbyScoreStore *self,
                             gint             score)
{
    g_return_if_fail (RUGBY_IS_SCORE_STORE (self));
    g_return_if_fail (score >= 0 && score <= 200);

    self->score = score;
    g_object_notify_by_pspec (G_OBJECT (self), pspecs[PROP_SCORE]);

    populate_store (self);
}