/*
   xml_team.c

   Bygfoot Football Manager -- a small and simple GTK2-based
   football management game.

   http://bygfoot.sourceforge.net

   Copyright (C) 2005  Gyözö Both (gyboth@bygfoot.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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

#include "file.h"
#include "free.h"
#include "main.h"
#include "misc.h"
#include "option.h"
#include "player.h"
#include "team.h"
#include "variables.h"
#include "xml_team.h"

/**
 * The tags used in the XML files defining teams.
 */
#define TAG_TEAM "team"
#define TAG_TEAM_NAME "team_name"
#define TAG_STADIUM_NAME "stadium_name"
#define TAG_SYMBOL "symbol"
#define TAG_AVERAGE_TALENT "average_talent"
#define TAG_FORMATION "formation"
#define TAG_NAMES_FILE "names_file"
#define TAG_PLAYER "player"
#define TAG_PLAYER_NAME "player_name"
#define TAG_PLAYER_BIRTH_YEAR "birth_year"
#define TAG_PLAYER_BIRTH_MONTH "birth_month"
#define TAG_PLAYER_SKILL "skill"
#define TAG_PLAYER_TALENT "talent"
#define TAG_PLAYER_POSITION "position"

enum XmlTeamStates
{
    STATE_TEAM = 0,
    STATE_TEAM_NAME,
    STATE_STADIUM_NAME,
    STATE_SYMBOL,
    STATE_AVERAGE_TALENT,
    STATE_FORMATION,
    STATE_NAMES_FILE,
    STATE_PLAYER,
    STATE_PLAYER_NAME,
    STATE_PLAYER_BIRTH_YEAR,
    STATE_PLAYER_BIRTH_MONTH,
    STATE_PLAYER_SKILL,
    STATE_PLAYER_TALENT,
    STATE_PLAYER_POSITION,
    STATE_END
};

gint state, birth_year;
Player new_player;
Team *team;
const gchar *d_file;

void
xml_team_read_start_element (GMarkupParseContext *context,
			    const gchar         *element_name,
			    const gchar        **attribute_names,
			    const gchar        **attribute_values,
			    gpointer             user_data,
			    GError             **error)
{
    if(strcmp(element_name, TAG_TEAM) == 0)
	state = STATE_TEAM;
    else if(strcmp(element_name, TAG_TEAM_NAME) == 0)
	state = STATE_TEAM_NAME;
    else if(strcmp(element_name, TAG_STADIUM_NAME) == 0)
	state = STATE_STADIUM_NAME;
    else if(strcmp(element_name, TAG_SYMBOL) == 0)
	state = STATE_SYMBOL;
    else if(strcmp(element_name, TAG_AVERAGE_TALENT) == 0)
	state = STATE_AVERAGE_TALENT;
    else if(strcmp(element_name, TAG_FORMATION) == 0)
	state = STATE_FORMATION;
    else if(strcmp(element_name, TAG_NAMES_FILE) == 0)
	state = STATE_NAMES_FILE;
    else if(strcmp(element_name, TAG_PLAYER) == 0)
    {
	state = STATE_PLAYER;
	new_player = player_new(team, ((gfloat)team->average_talent / 10000) * 
				const_float("float_player_max_skill"), TRUE);
    }
    else if(strcmp(element_name, TAG_PLAYER_NAME) == 0)
	state = STATE_PLAYER_NAME;
    else if(strcmp(element_name, TAG_PLAYER_BIRTH_YEAR) == 0)
	state = STATE_PLAYER_BIRTH_YEAR;
    else if(strcmp(element_name, TAG_PLAYER_BIRTH_MONTH) == 0)
	state = STATE_PLAYER_BIRTH_MONTH;
    else if(strcmp(element_name, TAG_PLAYER_SKILL) == 0)
	state = STATE_PLAYER_SKILL;
    else if(strcmp(element_name, TAG_PLAYER_TALENT) == 0)
	state = STATE_PLAYER_TALENT;
    else if(strcmp(element_name, TAG_PLAYER_POSITION) == 0)
	state = STATE_PLAYER_POSITION;
    else
	g_warning("xml_team_read_start_element: unknown tag: %s; I'm in state %d\n",
		  element_name, state);
}

/**
 * The function called by the parser when a closing tag is read.
 * The state variable is changed in this function.
 * @see The GLib manual (Simple XML parser).
 */
void
xml_team_read_end_element    (GMarkupParseContext *context,
			      const gchar         *element_name,
			      gpointer             user_data,
			      GError             **error)
{
    if(strcmp(element_name, TAG_TEAM_NAME) == 0 ||
       strcmp(element_name, TAG_STADIUM_NAME) == 0 ||
       strcmp(element_name, TAG_SYMBOL) == 0 ||
       strcmp(element_name, TAG_AVERAGE_TALENT) == 0 ||
       strcmp(element_name, TAG_FORMATION) == 0 ||
       strcmp(element_name, TAG_NAMES_FILE) == 0 ||
       strcmp(element_name, TAG_PLAYER) == 0)
    {
	state = STATE_TEAM;
	if(strcmp(element_name, TAG_PLAYER) == 0)
	{
	    if(team->players->len == const_int("int_team_cpu_players"))
	    {
		free_player(&new_player);
		main_exit_program(EXIT_LOAD_TEAM_DEF, 
				  "xml_team_read_end_element: too many players in team definition '%s' (only %d allowed).",
				  d_file, const_int("int_team_cpu_players"));
	    }
	    else
		g_array_append_val(team->players, new_player);
	}
    }
    else if(strcmp(element_name, TAG_PLAYER_NAME) == 0 ||
	    strcmp(element_name, TAG_PLAYER_BIRTH_YEAR) == 0 ||
	    strcmp(element_name, TAG_PLAYER_BIRTH_MONTH) == 0 ||
	    strcmp(element_name, TAG_PLAYER_SKILL) == 0 ||
	    strcmp(element_name, TAG_PLAYER_TALENT) == 0 ||
	    strcmp(element_name, TAG_PLAYER_POSITION) == 0)
	state = STATE_PLAYER;
    else if(strcmp(element_name, TAG_TEAM) != 0)
	g_warning("xml_team_read_end_element: unknown tag: %s; I'm in state %d\n",
		  element_name, state);
}

/**
 * The function called by the parser when the text between tags is read.
 * This function is responsible for filling in the variables (e.g. team names)
 * when a file gets loaded.
 * @see The GLib manual (Simple XML parser).
 */
void
xml_team_read_text         (GMarkupParseContext *context,
			   const gchar         *text,
			   gsize                text_len,  
			   gpointer             user_data,
			   GError             **error)
{
    gchar buf[text_len + 1];
    gint int_value;
    gfloat float_value;

    strncpy(buf, text, text_len);
    buf[text_len] = '\0';

    int_value = (gint)g_ascii_strtod(buf, NULL);
    float_value = (gfloat)g_ascii_strtod(buf, NULL);

    if(state == STATE_TEAM_NAME)
	misc_string_assign(&team->name, buf);
    else if(state == STATE_STADIUM_NAME)
    {
	g_free(team->stadium.name);
	misc_string_assign(&team->stadium.name, buf);
    }
    else if(state == STATE_SYMBOL)
	misc_string_assign(&team->symbol, buf);
    else if(state == STATE_AVERAGE_TALENT && opt_int("int_opt_load_defs") == 1)
	team->average_talent = 
	    (float_value / 10000) * const_float("float_player_max_skill");
    else if(state == STATE_FORMATION)
	team->structure = int_value;
    else if(state == STATE_NAMES_FILE)
	misc_string_assign(&team->names_file, buf);
    else if(state == STATE_PLAYER_NAME)
	misc_string_assign(&new_player.name, buf);
    else if(state == STATE_PLAYER_BIRTH_YEAR && opt_int("int_opt_load_defs") == 1)
	birth_year = int_value;
    else if(state == STATE_PLAYER_BIRTH_MONTH && opt_int("int_opt_load_defs") == 1)
	new_player.age = misc_get_age_from_birth(birth_year, int_value);
    else if(state == STATE_PLAYER_SKILL && opt_int("int_opt_load_defs") == 1)
	new_player.skill = ((gfloat)int_value / 10000) * 
	    const_float("float_player_max_skill");
    else if(state == STATE_PLAYER_TALENT && opt_int("int_opt_load_defs") == 1)
	new_player.talent = ((gfloat)int_value / 10000) * 
	    const_float("float_player_max_skill");
    else if(state == STATE_PLAYER_POSITION)
	new_player.pos = int_value;
}

/** Parse a team definition file and write the team accordingly. */
void
xml_team_read(Team *tm, const gchar *def_file)
{
    GMarkupParser parser = {xml_team_read_start_element,
			    xml_team_read_end_element,
			    xml_team_read_text, NULL, NULL};
    GMarkupParseContext *context;
    gchar *file_contents;
    gsize length;
    GError *error = NULL;

    team = tm;
    d_file = def_file;

    context = 
	g_markup_parse_context_new(&parser, 0, NULL, NULL);

    if(!g_file_get_contents(def_file, &file_contents, &length, &error))
    {
	g_warning("xml_team_read: error reading file %s\n", def_file);
	misc_print_error(&error, FALSE);
	return;
    }

    if(g_markup_parse_context_parse(context, file_contents, length, &error))
    {
	g_markup_parse_context_end_parse(context, NULL);	
	g_markup_parse_context_free(context);
	g_free(file_contents);
    }
    else
    {
	g_critical("xml_team_read: error parsing file %s\n", def_file);
	misc_print_error(&error, TRUE);
    }

    team_complete_def(team);
}
