#ifndef DRAWING_CPP
#define DRAWING_CPP
#include <core/inc.hpp>

void drawing_framework::c_drawing::skeleton( float p1, float p2, float p3, float p4, ImColor color, float thickness )
{
	ImGui::GetBackgroundDrawList( )->AddLine( ImVec2( p1, p2 ), ImVec2( p3, p4 ), color, thickness );
}

void drawing_framework::c_drawing::outlined_rectangle( ImVec2 size, ImVec2 location, ImColor col )
{
	auto drawList = ImGui::GetBackgroundDrawList( );
	ImVec2 windowPos = ImGui::GetWindowPos( );
	ImVec2 topLeft = ImVec2( location.x + windowPos.x, location.y + windowPos.y );
	ImVec2 bottomRight = ImVec2( topLeft.x + size.x, topLeft.y + size.y );
	drawList->AddRect( topLeft, bottomRight, col );
}

void drawing_framework::c_drawing::bounding_box( const math::vector3& position, const math::vector3& size, ImColor color ) {

	ImGui::GetBackgroundDrawList( )->AddRectFilled( ImVec2( position.x, position.y ), ImVec2( size.x + position.x, size.y + position.y ), ImColor( 0, 0, 0, 30 ) );

	ImGui::GetBackgroundDrawList( )->AddRect( ImVec2( position.x, position.y ), ImVec2( size.x + position.x, size.y + position.y ), color, 0.0f, 0, 1.f );
}

void drawing_framework::c_drawing::line( const ImVec2& from, const ImVec2& to, ImColor color, float thickness ) {
	ImGui::GetBackgroundDrawList( )->AddLine( from, to, color, thickness );
}

void drawing_framework::c_drawing::dashed_line( const ImVec2& start, const ImVec2& end, ImColor color, float thickness, float dash_length ) {

	float distance = std::hypot( end.x - start.x, end.y - start.y );
	ImVec2 direction = ImVec2( ( end.x - start.x ) / distance, ( end.y - start.y ) / distance );

	for ( float i = 0.0f; i < distance; i += dash_length * 2 ) {
		ImVec2 segment_start = ImVec2( start.x + direction.x * i, start.y + direction.y * i );
		ImVec2 segment_end = ImVec2( start.x + direction.x * std::min( i + dash_length, distance ),
			start.y + direction.y * std::min( i + dash_length, distance ) );

		line( segment_start, segment_end, color, thickness );
	}
}

void drawing_framework::c_drawing::dotted_line( const ImVec2& start, const ImVec2& end, ImColor color, float thickness, float dot_spacing ) {
	float distance = std::hypot( end.x - start.x, end.y - start.y );
	ImVec2 direction = ImVec2( ( end.x - start.x ) / distance, ( end.y - start.y ) / distance );

	for ( float i = 0.0f; i < distance; i += dot_spacing ) {
		ImVec2 dot_position = ImVec2( start.x + direction.x * i, start.y + direction.y * i );

		circle( dot_position.x, dot_position.y, thickness * 0.5f, color, 0.00f, true );
	}
}

void drawing_framework::c_drawing::add_image( IDirect3DTexture9* texture, const ImVec2& top_left, const ImVec2& bottom_right, ImColor color ) {
	ImGui::GetBackgroundDrawList( )->AddImage( texture, top_left, bottom_right, ImVec2( 0, 0 ), ImVec2( 1, 1 ), color );
}

void drawing_framework::c_drawing::triangle( ImVec2 x_point, ImVec2 y_point, ImVec2 z_point, ImColor color, bool outline, ImColor outline_color, bool fill, ImColor fill_color )
{
	if ( outline )
		ImGui::GetBackgroundDrawList( )->AddTriangle( x_point, y_point, z_point, outline_color, 1.4f );

	ImGui::GetBackgroundDrawList( )->AddTriangle( x_point, y_point, z_point, color, 1.f );

	if ( fill )
		ImGui::GetBackgroundDrawList( )->AddTriangleFilled( x_point, y_point, z_point, fill_color );
}


void drawing_framework::c_drawing::circle( float x, float y, float radius, ImColor color, float stroke, bool filled ) {
	if ( filled ) {
		ImGui::GetBackgroundDrawList( )->AddCircleFilled( ImVec2( x, y ), radius, color, 100 );
	}
	else {
		ImGui::GetBackgroundDrawList( )->AddCircle( ImVec2( x, y ), radius, color, 100, stroke );
	}
}

void drawing_framework::c_drawing::filled_rect( float x, float y, float width, float height, ImColor color, float rounding ) {
	ImGui::GetBackgroundDrawList( )->AddRectFilled( ImVec2( x, y ), ImVec2( width, height ), color, rounding );
}

auto drawing_framework::c_drawing::get_rbg_color( const float& frequency ) -> ImColor {

	auto now = std::chrono::high_resolution_clock::now( );
	float time = std::chrono::duration_cast< std::chrono::milliseconds >( now.time_since_epoch( ) ).count( ) / 1000.0f;

	int r = std::sin( frequency * time + 0 ) * 127 + 128;
	int g = std::sin( frequency * time + 2 ) * 127 + 128;
	int b = std::sin( frequency * time + 4 ) * 127 + 128;

	return ImColor( r, g, b );
}

auto drawing_framework::c_drawing::get_color( float r, float g, float b, enums::ColorMode mode, const float& frequency ) -> ImColor {

	switch ( mode )
	{
	case enums::ColorMode::Default:
		return ImColor( r, g, b );
	case enums::ColorMode::RGB:
		return get_rbg_color( frequency );
	case enums::ColorMode::Pastel:
		return ImColor( r * 0.8f + 0.2f, g * 0.8f + 0.2f, b * 0.8f + 0.2f );
	case enums::ColorMode::DPastel:
		return ImColor( r * 0.6f + 0.4f, g * 0.6f + 0.4f, b * 0.6f + 0.4f );
	case enums::ColorMode::Saturated:
		return ImColor( fmin( r * 1.5f, 1.0f ), fmin( g * 1.5f, 1.0f ), fmin( b * 1.5f, 1.0f ) );
	default:
		return ImColor( r, g, b );
	}

	return ImColor( r, g, b );
}

void drawing_framework::c_drawing::text( const std::string& input, ImVec2 pos, ImColor color, float size, ImFont* font, bool outline )
{
	if ( outline )
	{
		ImVec4 outlineColor = ImVec4( 0.0f, 0.0f, 0.0f, 1.0f );

		ImGui::GetBackgroundDrawList( )->AddText( font, size, ImVec2( pos.x - 1, pos.y - 1 ), IM_COL32( outlineColor.x * 255, outlineColor.y * 255, outlineColor.z * 255, outlineColor.w * 255 ), input.c_str( ), input.c_str( ) + input.size( ) );
		ImGui::GetBackgroundDrawList( )->AddText( font, size, ImVec2( pos.x + 1, pos.y - 1 ), IM_COL32( outlineColor.x * 255, outlineColor.y * 255, outlineColor.z * 255, outlineColor.w * 255 ), input.c_str( ), input.c_str( ) + input.size( ) );
		ImGui::GetBackgroundDrawList( )->AddText( font, size, ImVec2( pos.x - 1, pos.y + 1 ), IM_COL32( outlineColor.x * 255, outlineColor.y * 255, outlineColor.z * 255, outlineColor.w * 255 ), input.c_str( ), input.c_str( ) + input.size( ) );
		ImGui::GetBackgroundDrawList( )->AddText( font, size, ImVec2( pos.x + 1, pos.y + 1 ), IM_COL32( outlineColor.x * 255, outlineColor.y * 255, outlineColor.z * 255, outlineColor.w * 255 ), input.c_str( ), input.c_str( ) + input.size( ) );
	}

	ImGui::GetBackgroundDrawList( )->AddText( font, size, pos, color, input.c_str( ), input.c_str( ) + input.size( ) );
}

auto drawing_framework::c_drawing::render_radar_object( const ImVec2& projection, const float& radius, const ImColor& object_color, const bool& outline, const bool& show_distance, const int& distance, const ImColor& outline_color, const float& stroke ) -> void
{
	if ( outline ) {
		this->circle( projection.x, projection.y, radius + 1.f, outline_color, stroke, true );
	}

	this->circle( projection.x, projection.y, radius, object_color, stroke, true );

	if ( show_distance ) {
		this->text( std::to_string( distance ) + hash_str( "m" ), projection, ImColor( 255, 255, 255 ), 11.f, this->esp_font );
	}
}

auto drawing_framework::c_drawing::render_world_object( float& text_padding, const ImVec2& object_position, const std::string& object_name, const float& object_distance, const ImColor& object_color, const bool& display_distance, const bool& display_tier_name, const std::string& tier_name, const bool& display_box, const float& box_width, const float& box_height ) -> void
{
	ImVec2 text_size = ImGui::CalcTextSize( object_name.c_str( ) );

	this->text(
		object_name,
		ImVec2( object_position.x - ( text_size.x / 2 ), object_position.y - text_size.y ),
		object_color,
		g_vars->font.size,
		this->esp_font
	);

	text_padding += text_size.y;

	if ( display_distance )
	{
		std::string distance_string = hash_str( "[" ) + std::to_string( static_cast< int >( object_distance ) ) + hash_str( "m" ) + hash_str( "]" );
		ImVec2 distance_size = ImGui::CalcTextSize( distance_string.c_str( ) );

		this->text(
			distance_string,
			ImVec2( object_position.x - ( distance_size.x / 2 ), object_position.y - text_size.y + text_padding ),
			ImColor( 255, 255, 255 ),
			g_vars->font.size,
			this->esp_font
		);

		text_padding += distance_size.y;
	}

	if ( display_tier_name )
	{
		ImVec2 tier_size = ImGui::CalcTextSize( tier_name.c_str( ) );

		this->text(
			tier_name,
			ImVec2( object_position.x - ( tier_size.x / 2 ), object_position.y - text_size.y + text_padding ),
			object_color,
			g_vars->font.size,
			this->esp_font
		);

		text_padding += tier_size.y;
	}

	if ( display_box )
	{

	}
}

#endif