#include <gtk/gtk.h>
#include <gdk/gdk.h>

#include "player.h"
#include "client.h"
#include "gtkhelp_reports.h"

/**** HELPERS ****/

enum render_type_e {
    RENDER_AMOUNT,
    RENDER_PERCENTAGE,
    RENDER_INT,
    RENDER_STRING
};

static void
render_func_amount(GtkTreeViewColumn *col,
		   GtkCellRenderer *renderer,
		   GtkTreeModel *model,
		   GtkTreeIter *iter,
		   gpointer userdata)
{
    int column = (int)userdata;
    guint num;
    char amountstr[16];

    gtk_tree_model_get(model, iter, column, &num, -1);

    prettyprint_money(num, amountstr, sizeof(amountstr)-1);

    g_object_set(renderer, "text", amountstr, NULL);
}

static void
render_func_percentage(GtkTreeViewColumn *col,
		       GtkCellRenderer *renderer,
		       GtkTreeModel *model,
		       GtkTreeIter *iter,
		       gpointer userdata)
{
    int column = (int)userdata;
    guint num;
    char str[16];

    gtk_tree_model_get(model, iter, column, &num, -1);
    
    snprintf(str, sizeof(str)-1, "%d%%", num);

    g_object_set(renderer, "text", str, NULL);
}

static void
render_func_int(GtkTreeViewColumn *col,
		GtkCellRenderer *renderer,
		GtkTreeModel *model,
		GtkTreeIter *iter,
		gpointer userdata)
{
    int column = (int)userdata;
    guint num;
    char str[16];

    gtk_tree_model_get(model, iter, column, &num, -1);
    
    snprintf(str, sizeof(str)-1, "%d", num);

    g_object_set(renderer, "text", str, NULL);
}

static void
add_col(GtkTreeView *view, int prop, char *title, enum render_type_e type)
{
    GtkTreeViewColumn *col;
    GtkCellRenderer *renderer;

    col = gtk_tree_view_column_new();
    gtk_tree_view_column_set_title(col, title);
    gtk_tree_view_append_column(view, col);

    renderer = gtk_cell_renderer_text_new();
    gtk_tree_view_column_pack_start(col, renderer, TRUE);
	
    switch (type) 
	{
	case RENDER_AMOUNT:
	    gtk_tree_view_column_set_cell_data_func(col, renderer, &render_func_amount, 
						    (void *)prop, NULL);
	    break;
	case RENDER_INT:
	    gtk_tree_view_column_set_cell_data_func(col, renderer, &render_func_int, 
						    (void *)prop, NULL);
	    break;
	case RENDER_PERCENTAGE:
	    gtk_tree_view_column_set_cell_data_func(col, renderer, &render_func_percentage, 
						    (void *)prop, NULL);
	    break;
	case RENDER_STRING:
	    gtk_tree_view_column_add_attribute(col, renderer, "text", prop);
	    break;
    }
}

/**** FINANCES ****/

enum finance_item_e {
    FINANCE_TITLE = 0,
    FINANCE_THISMONTH,
    FINANCE_LASTMONTH,
    FINANCE_LASTYEAR,
    FINANCE_ALLTIME,
    FINANCE_NUMCOLS
};

char *finance_titles[] = {
    "Title",
    "This Month",
    "Last Month",
    "This Year",
    "Last Year",
    "All Time"
};

enum loans_item_e {
    LOANS_NUM = 0,
    LOANS_TITLE,
    LOANS_NUMCOLS
};

char *loans_titles[] = {
    "Num",
    "Loan"
};

static int
finances_fillin(char *title, int *amounts, void *rock)
{
    GtkListStore *list = (GtkListStore *)rock;
    GtkTreeIter iter;

    gtk_list_store_append(list, &iter);

    if (strcmp(title,"-") == 0) {
	gtk_list_store_set(list, &iter,
			   FINANCE_TITLE, "-----------------------------",
			   FINANCE_THISMONTH, 0,
			   FINANCE_LASTMONTH, 0,
			   FINANCE_LASTYEAR, 0,
			   FINANCE_ALLTIME, 0,
			   -1);
    } else {
	gtk_list_store_set(list, &iter,
			   FINANCE_TITLE, title,
			   FINANCE_THISMONTH, amounts[RANGE_CURRENT_MONTH],
			   FINANCE_LASTMONTH, amounts[RANGE_LAST_MONTH],
			   FINANCE_LASTYEAR, amounts[RANGE_CURRENT_YEAR],
			   FINANCE_ALLTIME, amounts[RANGE_ALLTIME],
			   -1);	
    }

    return 0;
}

static int
finances_loan_fillin(int num, char *string, void *rock)
{
    GtkListStore *list = (GtkListStore *)rock;
    GtkTreeIter iter;

    gtk_list_store_append(list, &iter);

    gtk_list_store_set(list, &iter,
		       LOANS_NUM, num,
		       LOANS_TITLE, string,
		       -1);	
}

extern void
update_finances_window(GtkWidget *finances_window, client_t *client)
{
    GtkTreeView *incomeview;
    GtkListStore *list;
    GtkTreeView *loanview;
    GtkListStore *loanlist;

    incomeview = (GtkTreeView *)lookup_widget(finances_window, "incomeview");
    loanview = (GtkTreeView *)lookup_widget(finances_window, "loansview");

    /* get the data */
    list = gtk_list_store_new(FINANCE_NUMCOLS, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_UINT, 
			      G_TYPE_UINT, G_TYPE_UINT);
    loanlist = gtk_list_store_new(LOANS_NUMCOLS, G_TYPE_INT, G_TYPE_STRING);

    client_getfinances(client, &finances_fillin ,list,
		       &finances_loan_fillin, loanlist);

    gtk_tree_view_set_model(incomeview, GTK_TREE_MODEL(list));
    g_object_unref(list);

    gtk_tree_view_set_model(loanview, GTK_TREE_MODEL(loanlist));
    g_object_unref(loanlist);

    gtk_widget_show (finances_window);
}

extern void
setup_finances_treeview(GtkWidget *finances_window)
{
    GtkTreeView *incomeview;
    GtkTreeViewColumn *col;
    GtkCellRenderer *renderer;
    int i;

    incomeview = (GtkTreeView *)lookup_widget(finances_window, "incomeview");

    col = gtk_tree_view_column_new();
    gtk_tree_view_column_set_title(col, finance_titles[FINANCE_TITLE]);
    gtk_tree_view_append_column(incomeview, col);

    renderer = gtk_cell_renderer_text_new();
    gtk_tree_view_column_pack_start(col, renderer, TRUE);

    gtk_tree_view_column_add_attribute(col, renderer, "text", FINANCE_TITLE);

    for (i = FINANCE_THISMONTH; i <= FINANCE_ALLTIME; i++) {
	add_col(incomeview, i, finance_titles[i], RENDER_AMOUNT);
    }

    gtk_tree_view_set_headers_visible(incomeview, TRUE);    

}

extern void
setup_loans_treeview(GtkWidget *finances_window)
{
    GtkTreeView *loansview;

    loansview = (GtkTreeView *)lookup_widget(finances_window, "loansview");

    add_col(loansview, LOANS_TITLE, loans_titles[LOANS_TITLE], RENDER_STRING);

    gtk_tree_view_set_headers_visible(loansview, TRUE);    

}


/********* STATS ***********/

char *stats_titles[] = {
    "Name",
    "Value"
};

enum stats_item_e {
    STATS_NAME = 0,
    STATS_VALUE,
    STATS_NUMCOLS
};

static void
stats_fillin(char *name, char *value, void *rock)
{
    GtkListStore *list = (GtkListStore *)rock;
    GtkTreeIter iter;

    gtk_list_store_append(list, &iter);

    gtk_list_store_set(list, &iter,
		       STATS_NAME, name,
		       STATS_VALUE, value,
		       -1);
}

extern void
update_stats_window(GtkWidget *stats_window, client_t *client)
{
    GtkTreeView *stats;
    GtkListStore *list;

    stats = (GtkTreeView *)lookup_widget(stats_window, "stats_treeview");

    /* get the data */
    list = gtk_list_store_new(STATS_NUMCOLS, G_TYPE_STRING, G_TYPE_STRING);
    client_getstats(client, &stats_fillin , list);

    gtk_tree_view_set_model(stats, GTK_TREE_MODEL(list));

    g_object_unref(list);

    gtk_widget_show (stats_window);
}

extern void
setup_stats_treeview(GtkWidget *stats_window)
{
    GtkTreeView *statsview;
    GtkTreeViewColumn *col;
    GtkCellRenderer *renderer;
    int i;

    statsview = (GtkTreeView *)lookup_widget(stats_window, "stats_treeview");

    /* name */
    col = gtk_tree_view_column_new();
    gtk_tree_view_column_set_title(col, stats_titles[STATS_NAME]);
    gtk_tree_view_append_column(statsview, col);

    renderer = gtk_cell_renderer_text_new();
    gtk_tree_view_column_pack_start(col, renderer, TRUE);

    gtk_tree_view_column_add_attribute(col, renderer, "text", STATS_NAME);

    /* value */
    col = gtk_tree_view_column_new();
    gtk_tree_view_column_set_title(col, stats_titles[STATS_VALUE]);
    gtk_tree_view_append_column(statsview, col);

    renderer = gtk_cell_renderer_text_new();
    gtk_tree_view_column_pack_start(col, renderer, TRUE);

    gtk_tree_view_column_add_attribute(col, renderer, "text", STATS_VALUE);

    gtk_tree_view_set_headers_visible(statsview, TRUE);    
}


/************* POPULATION REPORT **********/

enum pop_item_e {
    POP_NAME = 0,
    POP_SIZE,
    POP_INCOME,
    POP_HOUSED,
    POP_WORK,
    POP_HAPPY,
    POP_NUMCOLS
};

char *pop_titles[] = {
    "Age Group",
    "Size",
    "Income",
    "Housed",
    "Work",
    "Happy"
};

typedef struct popreport_group_s {
    int num;
    int num_over18;
    int avgincome;
    float avghappy;
    int housed;
    int work;
} popreport_group_t;

typedef struct popreport_data_s {
    popreport_group_t groups[100/5];
    popreport_group_t totalgroup;
} popreport_data_t;

static int 
popreport_fillin(int age, int edlevel, int size, int income, 
		 int housed, int work, int happy, void *rock)
{
    popreport_data_t *data = (popreport_data_t *)rock;
    popreport_group_t *group;
    popreport_group_t *totalgroup;

    group = &data->groups[age/5];
    totalgroup = &data->totalgroup;

    if (size) {
	group->avgincome = ((group->num * group->avgincome) + income * size)/(group->num + size);
	group->avghappy = ((group->num * group->avghappy) + happy * size)/(group->num + size);
	group->num += size;
	if (age >= 18) {
	    group->num_over18 += size;
	}
	group->housed += housed;
	group->work += work;

	totalgroup->avgincome = ((totalgroup->num * totalgroup->avgincome) + income * size)/(totalgroup->num + size);
	totalgroup->avghappy = ((totalgroup->num * totalgroup->avghappy) + happy * size)/(totalgroup->num + size);
	totalgroup->num += size;
	if (age >= 18) {
	    totalgroup->num_over18 += size;
	}
	totalgroup->housed += housed;
	totalgroup->work += work;
    }

    return 0;
}
    
static void
display_group(popreport_group_t *group, int minage, int maxage, GtkListStore *list)
{
    GtkTreeIter iter;
    char agestr[10];

    gtk_list_store_append(list, &iter);

    if (minage >= 0) {
	snprintf(agestr,sizeof(agestr)-1,"%d-%d",minage, maxage);
    } else {
	snprintf(agestr,sizeof(agestr)-1,_("Total"));
    }

    gtk_list_store_set(list, &iter,
		       POP_NAME, agestr,
		       POP_SIZE, group->num,
		       POP_INCOME, group->avgincome,
		       POP_HOUSED, group->num ? group->housed*100/group->num : 0,
		       POP_WORK, group->num_over18 ? group->work*100/group->num_over18 : 0,
		       POP_HAPPY, (int)group->avghappy,
		       -1);
}

extern void
update_population_report(GtkWidget *window, client_t *client)
{
    GtkTreeView *stats;
    GtkListStore *list;
    popreport_data_t data;
    int i;

    stats = (GtkTreeView *)lookup_widget(window, "pop_treeview");

    /* get the data */
    list = gtk_list_store_new(POP_NUMCOLS, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT,
			      G_TYPE_INT, G_TYPE_INT, G_TYPE_INT);
    memset(&data, 0, sizeof(popreport_data_t));
    client_getpopreport(client, &popreport_fillin, &data);

    /* put the data in the liststore */
    for (i = 0; i < 20; i++) {
	display_group(&data.groups[i], i*5, i*5+5, list);
    }
    display_group(&data.totalgroup, -1, -1, list);    

    gtk_tree_view_set_model(stats, GTK_TREE_MODEL(list));

    g_object_unref(list);

    gtk_widget_show(window);
}

extern void
setup_population_treeview(GtkWidget *window)
{
    GtkTreeView *view;
    GtkTreeViewColumn *col;
    GtkCellRenderer *renderer;
    int i;

    view = (GtkTreeView *)lookup_widget(window, "pop_treeview");

    /* Name */
    add_col(view, POP_NAME,   pop_titles[POP_NAME],   RENDER_STRING);
    add_col(view, POP_SIZE,   pop_titles[POP_SIZE],   RENDER_INT);
    add_col(view, POP_INCOME, pop_titles[POP_INCOME], RENDER_AMOUNT);
    add_col(view, POP_HOUSED, pop_titles[POP_HOUSED], RENDER_PERCENTAGE);
    add_col(view, POP_WORK,   pop_titles[POP_WORK],   RENDER_PERCENTAGE);
    add_col(view, POP_HAPPY,  pop_titles[POP_HAPPY],  RENDER_INT);

    gtk_tree_view_set_headers_visible(view, TRUE);    
}

/************** Info ***********/

char *info_titles[] = {
    "Name",
    "Value"
};

enum info_item_e {
    INFO_NAME = 0,
    INFO_VALUE,
    INFO_NUMCOLS
};

static void
mapspot_info_cb(char *name, char *value, void *rock)
{
    GtkListStore *list = (GtkListStore *)rock;
    GtkTreeIter iter;

    gtk_list_store_append(list, &iter);

    gtk_list_store_set(list, &iter,
		       INFO_NAME, name,
		       INFO_VALUE, value,
		       -1);
}

extern void
update_info_window(GtkWidget *window, client_t *client, int mapx, int mapy)
{
    GtkTreeView *view;
    GtkListStore *list;

    view = (GtkTreeView *)lookup_widget(window, "info_treeview");

    /* get the data */
    list = gtk_list_store_new(INFO_NUMCOLS, G_TYPE_STRING, G_TYPE_STRING);
    client_getspot_info(client, mapx, mapy, &mapspot_info_cb, list);

    gtk_tree_view_set_model(view, GTK_TREE_MODEL(list));

    g_object_unref(list);
}

extern void
setup_info_treeview(GtkWidget *window)
{
    GtkTreeView *view;

    view = (GtkTreeView *)lookup_widget(window, "info_treeview");

    add_col(view, INFO_NAME, info_titles[INFO_NAME], RENDER_STRING);
    add_col(view, INFO_VALUE, info_titles[INFO_VALUE], RENDER_STRING);

    gtk_tree_view_set_headers_visible(view, TRUE);    
}
