#include <stdlib.h>
#include <string.h>
#include "knowledge.h"
#include "asc.h"
#include "books.h"
#include "elwindows.h"
#include "gamewin.h"
#include "hud.h"
#include "multiplayer.h"
#include "stats.h"
#include "tabs.h"
#include "textures.h"
#include "translate.h"
#include "widgets.h"
#ifdef OPENGL_TRACE
#include "gl_init.h"
#endif
#ifndef ENGLISH
#include "init.h"
#endif //ENGLISH

int knowledge_win= -1;
int knowledge_menu_x= 100;
int knowledge_menu_y= 20;
int knowledge_menu_x_len= STATS_TAB_WIDTH;
int knowledge_menu_y_len= STATS_TAB_HEIGHT;
int knowledge_scroll_id= 13;
#ifdef ENGLISH
int knowledge_book_image_id;
int knowledge_book_label_id;
int knowledge_book_id= 0;
#endif //ENGLISH

knowledge knowledge_list[KNOWLEDGE_LIST_SIZE];
int knowledge_count= 0;

#ifndef ENGLISH
knowledge liste_actuelle_knowledge[KNOWLEDGE_LIST_SIZE];
int separation = 200;
int nb_cat=-1;
int cat = -1;
int ancien_nb_categorie;
int saut_ligne = 13;
typedef struct
{
    Uint8 num;
    char nom[100];
    Uint8 mouse_over;
    Uint8 click;
    Uint8 nbtotal;
    Uint8 nbpresent;
} categories;

#define MAX_CATEGORIES 30
categories categorie[MAX_CATEGORIES];

const translation_categ noms_categories[] =
{
	{"Armes", 0},
	{"Armures", 1},
	{"Bijoux", 2},
	{"Combat", 3},
	{"Cristaux", 4},
	{"Essences", 5},
	{"Extraction", 6},
	{"Fabrication", 7},
	{"Généralités", 8},
	{"Invocation", 9},
	{"Métallurgie", 10},
	{"Potions", 11},
	{"Inconnue", 12}
};
#endif //ENGLISH

char knowledge_string[400]="";

#ifdef ENGLISH
int add_knowledge_book_image() {
	// Book image
	int isize, tsize, tid, picsperrow, xtile, ytile, ssize, id;
	float ftsize, u, v, uend, vend;

	isize=256;
	tsize=51;
	ssize=100;
	tid=21;
	picsperrow=isize/tsize;
	xtile=tid%picsperrow;
	ytile=tid/picsperrow;
	ftsize=(float)tsize/isize;
	u=ftsize*xtile;
	v=-ftsize*ytile;
	uend=u+ftsize;
	vend=v-ftsize;
	id= load_texture_cache_deferred("textures/items1.bmp", 0);
	return image_add_extended(knowledge_win, 0, NULL, 500, 215, 50, 50, WIDGET_DISABLED, 1.0, 1.0, 1.0, 1.0, id, u, v, uend, vend, 0.05f);
}

int handle_knowledge_book()
{
	open_book(knowledge_book_id + 10000);
	// Bring the new window to the front               <----- Doesn't work. Is in front for the first usage, but not after that
	select_window(book_win);
	return 1;
}
#endif //ENGLISH

void check_book_known()
{
	static int last_checked_book = -1;
	if (your_info.researching != last_checked_book)
	{
		last_checked_book = your_info.researching;
		if ((your_info.researching >= knowledge_count) && (your_info.researching < sizeof(knowledge_list)))
			LOG_TO_CONSOLE(c_red2, unknown_book_long_str);
	}
}

#ifndef ENGLISH
// Recherche des livres de la categorie choisie
void change_cat ()
{
    int i, j;
    int trouve=0;
    ancien_nb_categorie = nombre_knowledge_cat;
    nombre_knowledge_cat=0;
    for (i=0; i <= knowledge_count; i++)
    {
        if ((knowledge_list[i].type == cat) && (knowledge_list[i].affiche))
        {
            trouve = 1;
            liste_actuelle_knowledge[nombre_knowledge_cat]=knowledge_list[i];
            nombre_knowledge_cat += 1;
        }
        if (trouve && (knowledge_list[i].type != cat))
        {
            for (j=nombre_knowledge_cat; j <= ancien_nb_categorie; j++)
            {
                liste_actuelle_knowledge[j].present = -1;
                liste_actuelle_knowledge[j].mouse_over = -1;
                liste_actuelle_knowledge[j].name[0] = '\0';
                liste_actuelle_knowledge[j].has_book = -1;
                liste_actuelle_knowledge[j].is_stored = -1;
                liste_actuelle_knowledge[j].affiche = -1;
                liste_actuelle_knowledge[j].type = -1;
                liste_actuelle_knowledge[j].id = -1;
                liste_actuelle_knowledge[j].click = 0;
            }
            break;
        }
    }
    // Suppression de la barre de defilement s'il n'y en a pas besoin
    if (nombre_knowledge_cat <= 15)
    {
        vscrollbar_set_bar_len(knowledge_win, knowledge_scroll_id, 0);
    }
    else
    {
        vscrollbar_set_bar_len(knowledge_win, knowledge_scroll_id, nombre_knowledge_cat-15);
    }
    vscrollbar_set_pos(knowledge_win,knowledge_scroll_id,-1);
}
#endif //ENGLISH

int display_knowledge_handler(window_info *win)
{
	int i,x=2,y=2;
	int progress = (125*your_info.research_completed+1)/(your_info.research_total+1);
	int scroll = vscrollbar_get_pos (knowledge_win, knowledge_scroll_id);
	char points_string[16];
	char *research_string;
#ifndef ENGLISH
	x+= separation+2;

    // On liste les categories
    for (i=0; i <= nb_cat; i++)
    {
        if (categorie[i].mouse_over)
        {
			glColor3f(0.1f,0.1f,0.9f);
        }
        else if (categorie[i].click)
        {
			glColor3f(0.8f,0.0f,0.0f);
        }
        else
        {
			float percent = (categorie[i].nbtotal>0) ? ((float)categorie[i].nbpresent / categorie[i].nbtotal) : 1;
			// on amoindrit tout pourcentage inferieur a 100% pour marquer la difference
			if (percent < 1) percent = percent * 0.6f;
			// couleur evolutive du blancs (0%) vers le vert (100%)
			glColor3f(1.0f - percent, 1.0f, 1.0f - percent);
        }
		draw_string_zoomed(4,2+saut_ligne*i, (unsigned char*)categorie[i].nom, 1, 0.8);
    }
#else //ENGLISH
	int rx = win->len_x - 15;
	int lx = win->len_x - 15 - (455-330);
	int points_pos;
	float font_ratio = 0.7;
	float max_name_x = (win->len_x-4)/2;
#endif //ENGLISH

	if(your_info.research_total &&
	   (your_info.research_completed==your_info.research_total))
		safe_snprintf(points_string, sizeof(points_string), "%s", completed_research);
	else
		safe_snprintf(points_string, sizeof(points_string), "%i/%i",your_info.research_completed,your_info.research_total);
	if(your_info.researching < knowledge_count)
	{
#ifndef ENGLISH
        int j;
        for (j=0; j <= knowledge_count; j++)
        {
            if (your_info.researching == knowledge_list[j].id)
            {
		        research_string = knowledge_list[j].name;
                break;
            }
        }
#else //ENGLISH
		research_string = knowledge_list[your_info.researching].name;
#endif //ENGLISH
	}
	else if (your_info.researching < sizeof(knowledge_list))
	{
		research_string = unknown_book_short_str;
	}
	else
	{
		research_string = not_researching_anything;
		points_string[0] = '\0';
		progress = 1;
	}

	glDisable(GL_TEXTURE_2D);
#ifndef ENGLISH
    // trait de separation
    glBegin(GL_LINES);
	    glColor4f(0.77f,0.57f,0.39f,1.0f);
        glVertex3i(separation, 0, 0);
        glVertex3i(separation, 200, 0);
    glEnd();
#endif //ENGLISH
	glColor3f(0.77f,0.57f,0.39f);
	glBegin(GL_LINES);
	// window separators
	glVertex3i(0,200,0);
	glVertex3i(win->len_x,200,0);
	glVertex3i(0,300,0);
	glVertex3i(win->len_x,300,0);
#ifndef ENGLISH
	//progress bar
	glVertex3i(445,315,0);
	glVertex3i(570,315,0);
	glVertex3i(445,335,0);
	glVertex3i(570,335,0);
	glVertex3i(445,315,0);
	glVertex3i(445,335,0);
	glVertex3i(570,315,0);
	glVertex3i(570,335,0);
	glEnd();
	glBegin(GL_QUADS);
	//progress bar
	glColor3f(0.40f,0.40f,1.00f);
	glVertex3i(446,316,0);
	glVertex3i(445+progress,316,0);
	glColor3f(0.10f,0.10f,0.80f);
	glVertex3i(445+progress,334,0);
	glVertex3i(446,334,0);
	glColor3f(0.77f,0.57f,0.39f);
	glEnd();
	glEnable(GL_TEXTURE_2D);
	//draw text
	draw_string_small(4,210,(unsigned char*)knowledge_string,4);
	glColor3f(1.0f,1.0f,1.0f);
	draw_string_small(10,320,(unsigned char*)researching_str,1);
	draw_string_small(100,320,(unsigned char*)research_string,1);
	draw_string_small(480,320,(unsigned char*)points_string,1);
#else //ENGLISH
	//progress bar
	glVertex3i(lx,315,0);
	glVertex3i(rx,315,0);
	glVertex3i(lx,335,0);
	glVertex3i(rx,335,0);
	glVertex3i(lx,315,0);
	glVertex3i(lx,335,0);
	glVertex3i(rx,315,0);
	glVertex3i(rx,335,0);
	glEnd();
	glBegin(GL_QUADS);
	//progress bar
	glColor3f(0.40f,0.40f,1.00f);
	glVertex3i(lx+1,316,0);
	glVertex3i(lx+progress,316,0);
	glColor3f(0.10f,0.10f,0.80f);
	glVertex3i(lx+progress,334,0);
	glVertex3i(lx+1,334,0);
	glColor3f(0.77f,0.57f,0.39f);
	glEnd();
	glEnable(GL_TEXTURE_2D);
	//draw text
	draw_string_small(4,210,(unsigned char*)knowledge_string,4);
	glColor3f(1.0f,1.0f,1.0f);
	draw_string_small(10,320,(unsigned char*)researching_str,1);
	draw_string_small(120,320,(unsigned char*)research_string,1);
	draw_string_small(lx+points_pos,320,(unsigned char*)points_string,1);
#endif //ENGLISH
	// Draw knowledges
#ifndef ENGLISH
	for(i = scroll; i < (scroll + 15); i++)
#else //ENGLISH
	for(i = 2*scroll; i < 2 * (scroll + 19); i++)
#endif //ENGLISH
	{
#ifndef ENGLISH
		if (liste_actuelle_knowledge[i].mouse_over)
#else //ENGLISH
		if (knowledge_list[i].mouse_over)
#endif //ENGLISH
		{
			glColor3f (0.1f,0.1f,0.9f);
		}
#ifndef ENGLISH
		else if (liste_actuelle_knowledge[i].click)
        {
            glColor3f (0.9f,0.0f,0.0f);
        }
#endif //ENGLISH
#ifndef ENGLISH
		else if (liste_actuelle_knowledge[i].present)
#else //ENGLISH
		else if (knowledge_list[i].present)
#endif //ENGLISH
		{
			glColor3f (0.0f, 0.8f, 0.0f);
		}
#ifndef ENGLISH
		else if (liste_actuelle_knowledge[i].is_stored)
#else //ENGLISH
		else if (knowledge_list[i].is_stored)
#endif //ENGLISH
		{
#ifdef ENGLISH
			glColor3f (0.9f, 0.9f, 0.9f);
#else //ENGLISH
			glColor3f (0.7f, 0.7f, 0.7f);
#endif //ENGLISH
		}
		else
		{
			glColor3f (0.5f, 0.5f, 0.5f);
		}

#ifdef ENGLISH
		/* truncate the string if it is too long */
		if ((get_string_width((unsigned char*)knowledge_list[i].name) * font_ratio) > max_name_x)
		{
			const char *append_str = "... ";
			size_t dest_max_len = strlen(knowledge_list[i].name)+strlen(append_str)+1;
			char *used_name = (char *)malloc(dest_max_len);
			truncated_string(used_name, knowledge_list[i].name, dest_max_len, append_str, max_name_x, font_ratio);
			draw_string_zoomed(x, y, (unsigned char*)used_name,1,font_ratio);
			/* if the mouse is over this line and its truncated, tooltip to full name */
			if (knowledge_list[i].mouse_over)
				show_help(knowledge_list[i].name, 0, win->len_y+5);
			free(used_name);
		}
		else
			draw_string_zoomed(x,y,(unsigned char*)knowledge_list[i].name,1,font_ratio);

		x += (win->len_x-20)/2;
		if (i % 2 == 1)
		{
			y += 10;
			x = 2;
		}
#else //ENGLISH
		draw_string_zoomed(x,y,(unsigned char*)liste_actuelle_knowledge[i].name,1,0.7);
        y += saut_ligne;
#endif //ENGLISH
	}
#ifdef OPENGL_TRACE
CHECK_GL_ERRORS();
#endif //OPENGL_TRACE
	return 1;
}

int mouseover_knowledge_handler(window_info *win, int mx, int my)
{
	int	i;

#ifndef ENGLISH
	for(i=0; i<=nombre_knowledge_cat; i++)
    {
        liste_actuelle_knowledge[i].mouse_over=0;
    }
    for (i=0; i<=nb_cat;i++)
    {
        categorie[i].mouse_over=0;
    }
#else //ENGLISH
	for(i=0;i<knowledge_count;i++)knowledge_list[i].mouse_over=0;
#endif //ENGLISH
	if(mx>win->len_x-20)
		return 0;
	if(my>192)
		return 0;
#ifndef ENGLISH
    if (mx >= separation)
    {
    	my/=saut_ligne;
        liste_actuelle_knowledge[my+vscrollbar_get_pos (knowledge_win, knowledge_scroll_id)].mouse_over=1;
    }
    else
    {
	    mx/=240;
    	my/=saut_ligne;
        categorie[mx+my].mouse_over=1;
    }
#else //ENGLISH
	mx = (mx < (win->len_x-20)/2) ?0 :1;
	my/=10;
	knowledge_list[mx+2*(my+vscrollbar_get_pos (knowledge_win, knowledge_scroll_id))].mouse_over=1;
#endif //ENGLISH
	return 0;
}


int click_knowledge_handler(window_info *win, int mx, int my, Uint32 flags)
{
	int x,y,idx;
	Uint8 str[3];

	x= mx;
	y= my;
	if(x > win->len_x-20)
		return 0;
	if(y > 192)
		return 0;

	if(flags&ELW_WHEEL_UP) {
		vscrollbar_scroll_up(knowledge_win, knowledge_scroll_id);
		return 1;
	} else if(flags&ELW_WHEEL_DOWN) {
		vscrollbar_scroll_down(knowledge_win, knowledge_scroll_id);
		return 1;
	} else {
#ifndef ENGLISH
        int i;
        // On clique dans la liste des livres
	    if (x >= separation)
        {
            // On clique bien sur une connaissance
            if ( y/saut_ligne + vscrollbar_get_pos (knowledge_win, knowledge_scroll_id) < nombre_knowledge_cat)
            {
                for (i=0; i<=nombre_knowledge_cat;i++)
                {
                    liste_actuelle_knowledge[i].click=0;
                }

        		y/=saut_ligne;
		        idx = y + vscrollbar_get_pos (knowledge_win, knowledge_scroll_id);
                liste_actuelle_knowledge[idx].click=1;
    		    if (idx < nombre_knowledge_cat)
    	        {
        			str[0] = GET_KNOWLEDGE_INFO;
    			    *(Uint16 *)(str+1) = SDL_SwapLE16((short)liste_actuelle_knowledge[idx].id);
    			    my_tcp_send(my_socket,str,3);
        		}
            }
    	}
        // On clique dans la liste des categories
        else
        {
            // On clique bien sur une categorie
            if (y/saut_ligne <= nb_cat)
            {
                for (i=0; i <=nb_cat; i++)
                {
                    categorie[i].click=0;
                }
    		    cat = y/saut_ligne;
                change_cat ();
                categorie[cat].click=1;
            }
        }
#else //ENGLISH
		x = (x < (win->len_x-20)/2) ?0 :1;
		y/=10;
		idx = x + 2 *(y + vscrollbar_get_pos (knowledge_win, knowledge_scroll_id));
		if(idx < knowledge_count)
			{
				str[0] = GET_KNOWLEDGE_INFO;
				*(Uint16 *)(str+1) = SDL_SwapLE16((short)idx);
				my_tcp_send(my_socket,str,3);
				// Check if we display the book image and label
				knowledge_book_id = idx;
				if (knowledge_list[idx].present && knowledge_list[idx].has_book) {
					widget_unset_flags (knowledge_win, knowledge_book_image_id, WIDGET_DISABLED);
					widget_unset_flags (knowledge_win, knowledge_book_label_id, WIDGET_DISABLED);
				} else {
					widget_set_flags(knowledge_win, knowledge_book_image_id, WIDGET_DISABLED);
					widget_set_flags(knowledge_win, knowledge_book_label_id, WIDGET_DISABLED);
				}
			}
#endif //ENGLISH
    }
	return 1;
}


void get_knowledge_list (Uint16 size, const char *list)
{
	int i;

	// make sure the entire knowledge list is 0 incase of short data
	for(i=0; i<KNOWLEDGE_LIST_SIZE; i++){
		knowledge_list[i].present= 0;
	}

	// watch for size being too large
	if(size*8 > KNOWLEDGE_LIST_SIZE){
		size= KNOWLEDGE_LIST_SIZE/8;
	}

	// now copy the data
	for(i=0; i<size; i++)
	{
#ifndef ENGLISH
        int j;
        int k;
        for (j=0; j<8; j++)
        {
            for (k=0; k < KNOWLEDGE_LIST_SIZE; k++)
            {
                if (knowledge_list[k].id == i*8+j)
                {
                    if (j == 0)
                    {
                        knowledge_list[k].present = list[i] & 0x01;
                    }
                    if (j == 1)
                    {
                        knowledge_list[k].present = list[i] & 0x02;
                    }
                    if (j == 2)
                    {
                        knowledge_list[k].present = list[i] & 0x04;
                    }
                    if (j == 3)
                    {
                        knowledge_list[k].present = list[i] & 0x08;
                    }
                    if (j == 4)
                    {
                        knowledge_list[k].present = list[i] & 0x10;
                    }
                    if (j == 5)
                    {
                        knowledge_list[k].present = list[i] & 0x20;
                    }
                    if (j == 6)
                    {
                        knowledge_list[k].present = list[i] & 0x40;
                    }
                    if (j == 7)
                    {
                        knowledge_list[k].present = list[i] & 0x80;
                    }
                    break;
                }
            }
        }
#else //ENGLISH
		knowledge_list[i*8+0].present= list[i] & 0x01;
		knowledge_list[i*8+1].present= list[i] & 0x02;
		knowledge_list[i*8+2].present= list[i] & 0x04;
		knowledge_list[i*8+3].present= list[i] & 0x08;
		knowledge_list[i*8+4].present= list[i] & 0x10;
		knowledge_list[i*8+5].present= list[i] & 0x20;
		knowledge_list[i*8+6].present= list[i] & 0x40;
		knowledge_list[i*8+7].present= list[i] & 0x80;
#endif //ENGLISH
	}
#ifndef ENGLISH
	// Pour finir on compatabilise les livres lus pour chaque categorie
	for (i=0; i < MAX_CATEGORIES; i++)
	{
		categorie[i].nbpresent = 0;
	}
	for (i=0; i < KNOWLEDGE_LIST_SIZE; i++)
	{
		if (knowledge_list[i].present) categorie[knowledge_list[i].type].nbpresent++;
	}
#endif //ENGLISH
}

void get_new_knowledge(Uint16 idx)
{
#ifndef ENGLISH
    int i;
    for (i=0; i <= knowledge_count; i++)
    {
        if (idx == knowledge_list[i].id)
        {
            knowledge_list[i].present = 1;
            categorie[knowledge_list[i].type].nbpresent++;
            break;
        }
    }
    // Permet de réinitaliser les connaissances si la fenêtre est ouverte
    change_cat ();
#else //ENGLISH
	if(idx < KNOWLEDGE_LIST_SIZE){
		knowledge_list[idx].present= 1;
	}
#endif //ENGLISH
}

void fill_knowledge_win ()
{
	set_window_handler(knowledge_win, ELW_HANDLER_DISPLAY, &display_knowledge_handler );
	set_window_handler(knowledge_win, ELW_HANDLER_CLICK, &click_knowledge_handler );
	set_window_handler(knowledge_win, ELW_HANDLER_MOUSEOVER, &mouseover_knowledge_handler );

#ifndef ENGLISH
	knowledge_scroll_id = vscrollbar_add_extended (knowledge_win, knowledge_scroll_id, NULL, knowledge_menu_x_len - 20,  0, 20, 200     , 0, 1.0, 0.77f, 0.57f, 0.39f, 0, 5, nombre_knowledge_cat-15);
#else //ENGLISH
	knowledge_scroll_id = vscrollbar_add_extended (knowledge_win, knowledge_scroll_id, NULL, knowledge_menu_x_len - 20,  0, 20, 200, 0, 1.0, 0.77f, 0.57f, 0.39f, 0, 10, (knowledge_count+2)/2-19);
	knowledge_book_image_id = add_knowledge_book_image();
	widget_set_OnClick(knowledge_win, knowledge_book_image_id, &handle_knowledge_book);
	knowledge_book_label_id = label_add_extended(knowledge_win, knowledge_book_image_id + 1, NULL, 485, 265, WIDGET_DISABLED, 0.8, 1.0, 1.0, 1.0, knowledge_read_book);
	widget_set_OnClick(knowledge_win, knowledge_book_label_id, &handle_knowledge_book);
#endif //ENGLISH
}

void display_knowledge()
{
	if(knowledge_win < 0)
	{
		knowledge_win= create_window("Knowledge", game_root_win, 0, knowledge_menu_x, knowledge_menu_y, knowledge_menu_x_len, knowledge_menu_y_len, ELW_WIN_DEFAULT);
		fill_knowledge_win ();
	}
	else
	{
		show_window(knowledge_win);
		select_window(knowledge_win);
	}
}

#ifndef ENGLISH
void init_categories()
{
	int i;

	// initialisation de la liste des categories
	for (i=0; i < MAX_CATEGORIES; i++)
	{
		categorie[i].nbpresent = 0;
		categorie[i].nbtotal = 0;
	}

	// on compte le nombre de categories presentes (en prenant le type max)
	// note: compter les categories differentes plutot que le max n'apporte rien,
	//       car en cas de trou les indices ne correspondraient plus
	nb_cat = -1;
	for (i=0; i < knowledge_count; i++)
	{
		if (knowledge_list[i].type < MAX_CATEGORIES)
		{
			if (knowledge_list[i].type > nb_cat) nb_cat = knowledge_list[i].type;
			categorie[knowledge_list[i].type].nbtotal++;
		}
	}

	// on affecte les noms aux categories
	for (i=0; i <= nb_cat; i++)
	{
		safe_snprintf(categorie[i].nom, sizeof(categorie[i].nom), "%s", noms_categories[(i<MAX_NOMS_KNOW) ? i : MAX_NOMS_KNOW]);
	}
}
#endif //ENGLISH

