#include <sstream>
#include <iomanip>
using std::ostringstream; using std::setprecision;

#include "gui/gui.h"
#include "gui/slider.h"
using namespace VGUI;


Slider::Slider( Widget* w )
{
	value = default_value = 0.0;
	setting = "";
	center = w->GetCenter();
	name = w->GetName();
	text = w->GetText();
	type = w->GetType();
	tip = w->GetTip();
	rel_width = w->GetRelWidth();
	rel_height = w->GetRelHeight();
	enabled = w->GetEnabled();
	selected = w->GetSelected();
	is_default = w->GetDefault();
	is_cancel = w->GetCancel();
	has_icon = w->GetHasIcon();
	width_auto = w->GetWidthAuto();
	height_auto = w->GetHeightAuto();
	font_size = w->GetFontSize();
	color_r = w->GetColorR();
	color_g = w->GetColorG();
	color_b = w->GetColorB();

	string skin_path = settings.GetSkinPath();
	slider.Load( skin_path + "/textures/widgets/sld_wedge.png", false );
	cursor.Load( skin_path + "/textures/widgets/sld_cursor.png", false );

	wedge_tex_width = 0.148;
	wedge_width = 0.1186;
	wedge_height = 0.1975;

	cursor_width = 0.0370;
	cursor_height = 0.04938;
	cursor_offset = value * ( wedge_width );

	is_percent = true;

	// width = spacing between left of text and wedge + wedge width
	if( width_auto )
	{
		rel_width = 0.36 + wedge_width;
	}

	// height = wedge texture height
	if( height_auto )
	{
		rel_height = cursor_height;
	}
}

Slider::~Slider()
{
}

void Slider::Draw()
{
	Draw( 1.0 );
}

void Slider::Draw( float opacity )
{
	float center_x = center.GetXPercent();
	float center_y = center.GetYPercent();
	float rel_width_half = rel_width / 2.0f;
	float rel_height_half = rel_height / 2.0f;
	cursor_offset = value * ( wedge_width - 0.013 );
	float gfx_opacity = selected ? 0.9 : enabled ? 0.75 : 0.4;
	float opacity_txt = selected ? 0.9 : enabled ? 0.75 : 0.4;

	// draw wedge and cursor
	utility.Draw2D( center_x - rel_width_half + 0.3,
	                center_y - rel_height_half,
	                center_x - rel_width_half + 0.3 + wedge_tex_width,
	                center_y + wedge_height,
	                &slider, 0.0, 0, gfx_opacity * opacity );
	utility.Draw2D( center_x - rel_width_half + 0.3 + cursor_offset + 0.004,
	                center_y - rel_height_half + 0.001,
	                center_x - rel_width_half + 0.3 + cursor_offset + 0.004 + cursor_width,
	                center_y + rel_height_half + 0.006,
	                &cursor, 0.0, 64, gfx_opacity * opacity );

	// draw text
	font.Print( center_x - rel_width_half, center_y - ( font.Height( text.c_str(), 1, font_size ) / 2.0f ), text.c_str(), 1, font_size, color_r, color_g, color_b, opacity_txt );

	// draw value
	ostringstream value_text;
	float adj_val = GetAdjustedValue();
	if( is_percent )
	{
		adj_val *= 100.0;
		value_text << int( adj_val );
		value_text << "%";
	}
	else
	{
		value_text << setprecision( 3 ) << adj_val;
	}
	font.Print( "digital", center_x + rel_width_half - 0.05, center_y - ( font.GetFontHeight( "digital", 0.625 ) / 2.0f ), value_text.str(), 0.625, color_r, color_g, color_b, opacity_txt );

	// draw tip
	if( selected && ( tip != "" ) )
		font.Print( 0.5 - ( font.Width( tip.c_str(), 1, 6 ) / 2.0f ), 0.90, tip.c_str(), 1, 6, 0.7, 0.7, 0.7, 0.9 * opacity );
}

void Slider::IncValuePress()
{
	if( value < 0.9 )
	{
		value += 0.1;
	}
	else
	{
		value = 1.0;
	}
}

void Slider::IncValueRelease()
{
}

void Slider::DecValuePress()
{
	if( value > 0.1 )
	{
		value -= 0.1;
	}
	else
	{
		value = 0.0;
	}
}

void Slider::DecValueRelease()
{
}

void Slider::Save()
{
	default_value = value;
	settings.Set( setting, GetAdjustedValue() );
}

void Slider::ResetValue()
{
	float default_val;
	settings.Get( setting, default_val );
	SetValue( ( default_val - min_val ) / ( max_val - min_val ) );
}

bool Slider::MouseOver( float x, float y )
{
	float min_x, min_y, max_x, max_y;
	min_x = center.GetXPercent() - ( rel_width / 2.0f );
	min_y = center.GetYPercent() - ( rel_height / 2.0f );
	max_x = center.GetXPercent() + ( rel_width / 2.0f );
	max_y = center.GetYPercent() + ( rel_height / 2.0f ) + 0.01;

	return ( x > min_x ) && ( x < max_x ) && ( y > min_y ) && ( y < max_y );
}

string Slider::MousePress( float x, float y )
{
	float min_x, max_x, x_len, x_offset, new_value = value;
	min_x = center.GetXPercent() - ( rel_width / 2.0f ) + 0.364;
	max_x = center.GetXPercent() - ( rel_width / 2.0f ) + 0.36 + wedge_width - 0.009;

	if( ( x >= min_x ) && ( x <= max_x ) )
	{
		x_offset = x - min_x;
		x_len = max_x - min_x;

		new_value = x_offset / x_len;
	}
	else if( x < min_x )
	{
		new_value = 0.0;
	}
	else if( x > max_x )
	{
		new_value = 1.0;
	}

	SetValue( new_value );

	return "";
}

string Slider::MouseRelease( float x, float y )
{
	return "";
}

float Slider::GetAdjustedValue() const
{
	float adjusted_val = min_val + ( max_val - min_val ) * value;
	return ( adjusted_val < min_val ) ? min_val :
	       ( adjusted_val > max_val ) ? max_val : adjusted_val;
}
