#include "PrefData.h"
#include "defs.h"

PrefData ThePrefs;
CalcTables TheTables;

CalcTables::CalcTables()
{
//Create transparency calculation tables

	//Table is 100 x 256
	int32 aa,bb,tmp;
	aa = 0;
	bb = 0;
	//not past 101 - Mr. Lema didn't know why, but I'll figure it out later -- DW
	while (aa!=100+1)	// 100 is the maximum pressure
	{
		while (bb!=255+1)	// maximum value for a color channel
		{
			//transp_table[aa][bb] = value;
			// for array[0][0]:

			// Some bizarre math here which is rather inefficient. Trying 255 instead of 256.
//			tmp = int32 ((((float(bb))/256)+(1-((float(bb))/256) )*(float(aa)/100))*100);
			tmp = int32 ((((float(bb))/255)+(1-((float(bb))/255) )*(float(aa)/100))*100);
			if (tmp > 255)
				tmp=255; 
			if (tmp < 1)
				tmp = 1;
			tab_transp[aa][bb] =  uint8(tmp);
//			printf("\ntab_transp: %d",tmp);
			
			tmp = int32 (((aa*bb)/100));
			if (tmp > 255)
				tmp=255;
			if (tmp <0)
				tmp=0;
			tab_pourcent_x_val[aa][bb]= uint8(tmp);

			// when bb hits 256 this is probably going to have some serious problems. Trying 256-bb
//			tmp = int32(((float(255-bb)/256)*100)+aa); 
			tmp = int32(((float(256-bb)/256)*100)+aa); 
			if (tmp <0)
				tmp=0;
			if (tmp >100)
				tmp=100;
			tab_mask_transp[aa][bb] = uint8(tmp);
			
			// Draw Modes
			tmp= uint8( (float(100-aa)/100)*bb);
			if (tmp > 255)
				tmp=255;
			if (tmp < 0)
				tmp=0;
			tab_normal[aa][bb] = uint8(tmp); 

			tmp = int32(bb*1.3);
			if (tmp > 255)
				tmp=255;
			tab_lighten[aa][bb] = uint8 ((float(100-aa)/100)*tmp);

			tmp = int32(bb/1.3);
			if (tmp < 0)
				tmp=0;
			tab_darken[aa][bb]  = uint8 ((float(100-aa)/100)*tmp);
			
			bb++;
		}
		bb=0;
		aa++;
	} 

//-----------------------------------------------------------------------
				
	// 256x256 Table
	aa = 0;
	bb = 0;
	while (aa!=255+1)
	{
		while (bb!=255+1)
		{
			
			tmp = aa+bb;
			if (tmp>255)
				tmp= 255;
			if (tmp<0)
				tmp= 0;
			tab_addition[aa][bb] = uint8(tmp);
			
			tab_multiply[aa][bb] = uint8 (bb*(float(aa)/256));
			tab_difference[aa][bb] = bb-aa;
			if (aa < bb)
				tmp = bb;
			else
				tmp=aa;
			tab_combine[aa][bb] = tmp;
			bb++;
		}
		bb=0;
		aa++;
	}


	// one-dimensional table 

	aa = 0;

	while (aa!=255+1)
	{
		tmp =uint32((float(aa) / 256) *100);
		if (tmp>100)
			tmp=100;
		tab_char_to_percent[aa]  = 	100-uint8(tmp); 
		tmp =uint32((float(aa) / 256) *100);
		tmp= 50+tmp/2;
		if (tmp>100)
			tmp=100;	 // like above, but shaded
		tab_char_to_shade[aa]  = 	uint8(tmp); 

		// Brush transparency is stored as a float 0-1 * 100
		aa++;
	}

	int8 i;
	double current_radian;
	#ifndef PI
		#define PI 3.14159265358979323846
	#endif
	
	for(i=0;i<90; i++)
	{	current_radian=(180 * i)/PI;
	
		// Do 4 assignments, taking advantage of sin/cos symmetry
		sintable[i]=(float)sin(current_radian);
		sintable[i+90]=sintable[i];
		sintable[i+180]=-1 * sintable[i];
		sintable[i+270]=sintable[i+180];
		
		costable[i]=(float)cos(current_radian);
		costable[i+90]=-1 *costable[i];
		costable[i+180]=-1 *costable[i+90];
		costable[i+270]=costable[i];
	}
}

uint16 CalcTables::InvSine(float value)
{	// Returns the inverse sine of a value in the range 0 <= value <= 1 via 
	//	reverse-lookup any value out of range causes the function to return 0
	uint16 i=90;
	
	// Filter out bad values
	if(value > 1 || value < 0)
		return 0;
		
	while(value < sintable[i])
		i--;

	// current sintable[i] is less than value. Pick the degree value which is closer
	// to the passed value
	if( (value - sintable[i]) > (sintable[i+1] - value) )
		return (i+1);
	
	return i;		// value is closer to previous
}

PrefData::PrefData()
{
	
	//ca c'est pas vraiment des prefs... c'est pourquoi qu'elles sont pas dans Reset.
	//comme ça que c'est qu'on me comprends quand j'ai la commentaire que c'est clair dans la tête
	mask_mode=OFF;
	mask_activated=ON;

	no_pictures_left=ON;


}


void PrefData::ResetPrefs()
{
max_undo=32; //ATTENTION PAS PLUS DE 256.. le tableau ne doit pas etre en int32 sinon ça merde.. et bon 256 c'est assez non? non parce-que là une question m'interpelle mon vieux, tu vas lire ce putain de commentaire jusqu'où?

save_with_thumb = B_CONTROL_ON; //par défaut on sauve le thumb
tolerance=0;

rgb_color c = {255,0,0,0}; 
rgb_color d = {200,0,0};
rgb_color e = {0,150,255};
rgb_color f = {0,200,0};
rgb_color g = {255,150,0};
rgb_color hh = {255,50,0};
  
masking_color = c;
color_filter = d;
color_memorize = e;
color_undo = f;
color_load = g;
color_save = hh;

show_only_images = B_CONTROL_ON;
show_thumbs = B_CONTROL_ON;


fore_selector_size=2; //nb de fois à diviser les coordonnées, faudrait éviter autre que 1 ou 2...;-)
back_selector_size=2; //nb de fois à diviser les coordonnées, faudrait éviter autre que 1 ou 2...;-)

//positions par défaut
//brushes_frame.Set(20,120,20+3*64+B_V_SCROLL_BAR_WIDTH,120+3*64);
brushes_frame.Set(60,120,260,350); 
paper_frame = brushes_frame;
layer_frame = brushes_frame;
layer_frame.right += 56+20; 

paper_frame.OffsetBy(100,20); //évitons le chevauchement
fore_color_frame.Set( 200,200,
				 200+((256+32)/fore_selector_size),
				 200+((256+25)/fore_selector_size)-13);
	
back_color_frame = fore_color_frame; 
back_color_frame.OffsetBy(fore_color_frame.Width()+16,32); 
				 

pref_frame.Set(200,200,200+320-1,200+240-1);

info_frame.Set(0,0,192,128); info_frame.OffsetBy(300,60); 
option_frame.Set(0,0,192,192); option_frame.OffsetBy(300,200); 
navigation_frame.Set(0,0,192,128); navigation_frame.OffsetBy(300,300); 

tool_frame.Set(8,80,8+(24*2)-1,80+(9*23)-1+48+48-2+14);

texttool_frame=BRect(100,100,600,500);

//par défaut toutes les fenêtres sont fermées
create_win_open=false;
info_win_open=false;
option_win_open = false;
tool_win_open=false;
navigation_win_open=false;
fore_selector_open=false;
back_selector_open=false;
brush_selector_open=false;
paper_selector_open=false;
layer_selector_open = false;
pref_win_open = false;
save_panel_open=false;
open_panel_open=false;

limit_levels_open = false ;
range_selection_open = false ;
	
paper_size=64;
brush_size=32;
perso_brush_size=64;

pref_units = UNIT_CM;
pref_res_type = DPI;

sprintf(lang_name,"English");

}

void PrefData::Load()
{

	//------------------------------- READ PREFS MSG----------------------------------//	

	//effectué à l'ouverture de la window
	TextMessage *my_prefs  =  new TextMessage();
	
	char full_path[NAME_SIZE];
	sprintf(full_path,PREFS_DIR"/"); //le slash est pas dedans
	strcat(full_path,"BPM_Settings");
	
//	BAlert *alert;
	BFile x;
	
	if (x.SetTo(full_path,B_READ_ONLY)!=B_OK)
	{
		//LANGUAGE EST PAS ENCORE ACCESSIBLE, Tant pis...
		//alert = new BAlert(NULL,Language.get("COULD_NOT_LOAD_PREFS"), 

		// Ditching the alert on new preferences. Just make the new ones, already!		
/*		alert = new BAlert(NULL,"Error: could not load preferences file. Resetting to defaults.", 
	                  "OK",NULL,NULL,B_WIDTH_FROM_WIDEST,B_WARNING_ALERT); 
		alert->Go(NULL); //null pour pas qu'il arrête le reste
*/
		ThePrefs.ResetPrefs();
		ThePrefs.Save();
	
		return; //don't go any further.
	}

	my_prefs->ReadFromTextFile(full_path, my_prefs);
	
	
	
	//----------------------- ANALYZE AND DISPATCH PREFS MSG----------------------//	


	//units
	 my_prefs->FindInt32("units",&pref_units);
		
	//res_type
	my_prefs->FindInt32("res_type",&pref_res_type);



	//language
	const char *ptr = (char*) malloc (256);
	if (my_prefs->FindString("language", &ptr)!=B_OK) 
			 printf("\nError... language not found. Using English.");
	else sprintf(lang_name,ptr);

	//si je fais ça ça plante.... bon tant pis pour 256 bytes..
	//free(ptr); 

	//le menage derrière soi...
	delete my_prefs; 
}

void PrefData::Save()
{

	TextMessage my_prefs('nprf');
	
	
	//------------------------------- Prepare message ----------------------------------//	
		
	//UNITS
	my_prefs.AddInt32("units",ThePrefs.pref_units);

	//RES_type
	my_prefs.AddInt32("res_type",ThePrefs.pref_res_type);

	//language (attention on sauve une string avec le nom et non pas le numéro de l'index!
	//comme ça quand on relit les prefs il y a pas de prob s'il y a de nouveaux filez..
	my_prefs.AddString("language",ThePrefs.lang_name); 

	//------------------------------- WRITE PREFS MSG----------------------------------//	

	//MAKE SURE DIRECTORY EXISTS
	BDirectory d,t;
	
	char full_path[NAME_SIZE];
			  
	if (d.SetTo(PREFS_DIR)!=B_OK)  t.CreateDirectory(PREFS_DIR, &d);
				//if (d.SetTo(PREFS_DIR"/")!=B_OK)  system("mkdir "PREFS_DIR);
	sprintf(full_path,PREFS_DIR"/BPM_Settings"); //le slash est pas dedans
	
	BAlert *alert;
	//Write the preferences to the file
	if (my_prefs.WriteToTextFile(full_path) != B_OK)
	{
		//no languageclass here...
		alert = new BAlert(NULL,"Error, could not save preferences!", 
                    "OK",NULL,NULL,B_WIDTH_FROM_WIDEST,B_WARNING_ALERT); 
   		alert->Go(NULL); //null pour pas qu'il arrête le reste
	}

	//----------------------------------------------------------------------------//	

}
