#include "CAndromedaMenu.hpp"

#include <cstdio>

#include <ImGui/imgui.h>
#include <ImGui/imgui_internal.h>

#include <AndromedaClient/Settings/Settings.hpp>
#include <AndromedaClient/CAndromedaGUI.hpp>
#include <AndromedaClient/Features/CInventoryChanger/CInventoryItemsManager.hpp>

static CAndromedaMenu g_CAndromedaMenu{};

auto CAndromedaMenu::GetUIScale() -> float
{
	float Scale = ImGui::GetIO().DisplaySize.y / 1080.f;

	if ( Scale < 0.75f )
		Scale = 0.75f;

	if ( Scale > 2.0f )
		Scale = 2.0f;

	return Scale;
}

auto CAndromedaMenu::OnRenderMenu() -> void
{
	m_fUIScale = GetUIScale();

	ImGui::GetIO().FontGlobalScale = m_fUIScale;

	const ImVec2 DisplaySize = ImGui::GetIO().DisplaySize;

	float MenuW = 720.f * m_fUIScale;
	float MenuH = 560.f * m_fUIScale;

	if ( MenuW > DisplaySize.x - 16.f )
		MenuW = DisplaySize.x - 16.f;

	if ( MenuH > DisplaySize.y - 16.f )
		MenuH = DisplaySize.y - 16.f;

	ImGui::SetNextWindowSize( ImVec2( MenuW , MenuH ) , ImGuiCond_Always );
	ImGui::SetNextWindowPos( ImVec2( ( DisplaySize.x - MenuW ) * 0.5f , ( DisplaySize.y - MenuH ) * 0.5f ) , ImGuiCond_Always );

	if ( ImGui::Begin( XorStr( "Evicted" ) , nullptr , ImGuiWindowFlags_NoCollapse ) )
	{
		if ( ImGui::BeginTabBar( "##MainTabs" ) )
		{
			if ( ImGui::BeginTabItem( "Visuals" ) )
			{
				RenderVisualPanel();
				ImGui::EndTabItem();
			}

			if ( ImGui::BeginTabItem( "Glow & Chams" ) )
			{
				RenderGlowPanel();
				ImGui::EndTabItem();
			}

			if ( ImGui::BeginTabItem( "Skins" ) )
			{
				RenderSkinPanel();
				ImGui::EndTabItem();
			}

			if ( ImGui::BeginTabItem( "Music Kit" ) )
			{
				RenderMusicPanel();
				ImGui::EndTabItem();
			}

			if ( ImGui::BeginTabItem( "Misc" ) )
			{
				RenderMiscPanel();
				ImGui::EndTabItem();
			}

			if ( ImGui::BeginTabItem( "Config" ) )
			{
				RenderConfigPanel();
				ImGui::EndTabItem();
			}

			ImGui::EndTabBar();
		}
	}

	ImGui::End();
}

auto CAndromedaMenu::RenderVisualPanel() -> void
{
	ImGui::SeparatorText( "Visuals" );

	Checkbox( "Enabled" , Settings::Visual::Active );
	Checkbox( "Teammates" , Settings::Visual::Team );
	Checkbox( "Enemies" , Settings::Visual::Enemy );
	Checkbox( "Only Visible" , Settings::Visual::OnlyVisible );

	ImGui::SeparatorText( "Player Info" );

	Checkbox( "Name ESP" , Settings::Visual::NameESP );
	Checkbox( "Health ESP" , Settings::Visual::HealthESP );
	Checkbox( "Armor ESP" , Settings::Visual::ArmorESP );
	Checkbox( "Weapon ESP" , Settings::Visual::WeaponESP );
	Checkbox( "Bomb ESP" , Settings::Visual::BombESP );

	ImGui::SeparatorText( "Player Box" );

	Checkbox( "Player Box" , Settings::Visual::PlayerBox );

	const char* PlayerBoxTypeItems[] =
	{
		"Box" , "Outline Box" , "Coal Box" , "Outline Coal Box" , "Circle 3D" , "Glassy Box"
	};

	if ( Combo( "Type" , Settings::Visual::PlayerBoxType , PlayerBoxTypeItems , IM_ARRAYSIZE( PlayerBoxTypeItems ) ) )
	{
		if ( Settings::Visual::PlayerBoxType == 5 )
			Settings::Visual::GlassyBox = true;
		else
			Settings::Visual::GlassyBox = false;
	}

	if ( Settings::Visual::PlayerBoxType == 5 )
		SliderInt( "Glass Opacity" , Settings::Visual::GlassOpacity , 10 , 90 , "%d%%" );

	ImGui::SeparatorText( "Skeleton" );

	Checkbox( "Bone ESP" , Settings::Visual::BoneESP );

	if ( Settings::Visual::BoneESP )
	{
		Checkbox( "  Teammates" , Settings::Visual::BoneESPTeam );
		Checkbox( "  Enemies" , Settings::Visual::BoneESPEnemy );
	}
}

auto CAndromedaMenu::RenderGlowPanel() -> void
{
	ImGui::SeparatorText( "Glow" );

	Checkbox( "Glow Enabled" , Settings::Visual::Glow );

	if ( Settings::Visual::Glow )
	{
		Checkbox( "  Teammates" , Settings::Visual::GlowTeam );
		Checkbox( "  Enemies" , Settings::Visual::GlowEnemy );

		ImGui::NewLine();

		ColorEdit( "Glow TT" , &Settings::Colors::Visual::GlowTT.x );
		ColorEdit( "Glow TT Visible" , &Settings::Colors::Visual::GlowTT_Visible.x );
		ColorEdit( "Glow CT" , &Settings::Colors::Visual::GlowCT.x );
		ColorEdit( "Glow CT Visible" , &Settings::Colors::Visual::GlowCT_Visible.x );
	}

	ImGui::SeparatorText( "Chams" );

	Checkbox( "Material Chams" , Settings::Chams::Enabled );

	if ( Settings::Chams::Enabled )
	{
		Checkbox( "Through Walls" , Settings::Chams::IgnoreZ );

		ImGui::NewLine();

		ColorEdit( "Visible Color" , &Settings::Chams::Visible.x );
		ColorEdit( "Occluded Color" , &Settings::Chams::Occluded.x );
	}

	ImGui::SeparatorText( "Glassy Box" );

	Checkbox( "Glass Fill" , Settings::Visual::GlassyBox );

	if ( Settings::Visual::GlassyBox )
	{
		SliderInt( "Opacity" , Settings::Visual::GlassOpacity , 10 , 90 , "%d%%" );

		ImGui::NewLine();

		ColorEdit( "Box TT" , &Settings::Colors::Visual::PlayerBoxTT.x );
		ColorEdit( "Box CT" , &Settings::Colors::Visual::PlayerBoxCT.x );
	}
}

auto CAndromedaMenu::RenderSkinPanel() -> void
{
	auto* pManager = GetInventoryItemsManager();

	if ( pManager->GetDumpedItems().empty() )
		pManager->ScanAllItems();

	ImGui::TextColored( ImVec4( 1.f , 1.f , 1.f , 0.4f ) , "%s" , "Select a weapon on the left, then click a skin to apply it instantly." );

	ImGui::NewLine();

	const float ItemWidth = ImGui::GetContentRegionAvail().x * 0.42f;

	if ( ImGui::BeginChild( "##WeaponList" , ImVec2( ItemWidth , 0.f ) , true ) )
	{
		const auto& Items = pManager->GetDumpedItems();

		for ( size_t i = 0; i < Items.size(); i++ )
		{
			const auto& Item = Items[ i ];

			if ( Item.m_ItemType == CInventoryItemsManager::EDumpedItemType_t::DUMPED_ITEM_TYPE_MUSIC )
				continue;

			if ( Item.m_ItemType == CInventoryItemsManager::EDumpedItemType_t::DUMPED_ITEM_TYPE_AGENT )
				continue;

			const bool bSel = ( static_cast<int>( i ) == m_iSelectedItemIdx );

			char szLabel[ 128 ];
			std::snprintf( szLabel , sizeof szLabel , "%s (%u)" , Item.m_DisplayName.c_str() , Item.m_DefIdx );

			if ( ImGui::Selectable( szLabel , bSel ) )
			{
				m_iSelectedItemIdx = static_cast<int>( i );
				m_iSelectedSkinIdx = 0;
			}
		}
	}

	ImGui::EndChild();

	ImGui::SameLine();

	if ( ImGui::BeginChild( "##SkinList" , ImVec2( 0.f , 0.f ) , true ) )
	{
		const auto& Items = pManager->GetDumpedItems();

		if ( m_iSelectedItemIdx >= 0 && m_iSelectedItemIdx < static_cast<int>( Items.size() ) )
		{
			const auto& Item = Items[ m_iSelectedItemIdx ];

			ImGui::TextColored( ImVec4( 1.f , 1.f , 1.f , 0.9f ) , "%s" , Item.m_DisplayName.c_str() );

			ImGui::Separator();

			if ( Item.m_ItemType == CInventoryItemsManager::EDumpedItemType_t::DUMPED_ITEM_TYPE_GLOVE ||
				 Item.m_ItemType == CInventoryItemsManager::EDumpedItemType_t::DUMPED_ITEM_TYPE_KNIFE ||
				 Item.m_ItemType == CInventoryItemsManager::EDumpedItemType_t::DUMPED_ITEM_TYPE_WEAPON )
			{
				for ( size_t j = 0; j < Item.m_DumpedSkins.size(); j++ )
				{
					const auto& Skin = Item.m_DumpedSkins[ j ];

					const bool bSel = ( static_cast<int>( j ) == m_iSelectedSkinIdx );

					char szLabel[ 256 ];
					std::snprintf( szLabel , sizeof szLabel , "%s  [%s]" , Skin.m_DisplayName.c_str() , pManager->GetRarityName( Skin.m_Rarity ).c_str() );

					const ImU32 Rarity = pManager->GetRarityColor( Skin.m_Rarity );

					ImGui::PushStyleColor( ImGuiCol_Header , Rarity );

					if ( ImGui::Selectable( szLabel , bSel ) )
					{
						m_iSelectedSkinIdx = static_cast<int>( j );

						pManager->RequestWeaponSkin( Item.m_DefIdx , Skin.m_ID );
					}

					ImGui::PopStyleColor();
				}

				ImGui::NewLine();

				if ( ImGui::Button( "Remove" , ImVec2( 120.f * m_fUIScale , 28.f * m_fUIScale ) ) )
					pManager->RequestRemoveWeaponSkin( Item.m_DefIdx );
			}
		}
		else
		{
			ImGui::TextColored( ImVec4( 1.f , 1.f , 1.f , 0.4f ) , "%s" , "No weapon selected." );
		}
	}

	ImGui::EndChild();
}

auto CAndromedaMenu::RenderMusicPanel() -> void
{
	auto* pManager = GetInventoryItemsManager();

	if ( pManager->GetDumpedItems().empty() )
		pManager->ScanAllItems();

	ImGui::TextColored( ImVec4( 1.f , 1.f , 1.f , 0.4f ) , "%s" , "Click a music kit to apply it instantly. Selecting a new kit replaces the previous one." );

	ImGui::NewLine();

	if ( ImGui::BeginChild( "##MusicList" , ImVec2( 0.f , 0.f ) , true ) )
	{
		const auto& Items = pManager->GetDumpedItems();

		for ( const auto& Item : Items )
		{
			if ( Item.m_ItemType != CInventoryItemsManager::EDumpedItemType_t::DUMPED_ITEM_TYPE_MUSIC )
				continue;

			for ( const auto& Skin : Item.m_DumpedSkins )
			{
				const bool bSel = ( Skin.m_ID == pManager->GetMusicSelection() );

				if ( ImGui::Selectable( Skin.m_DisplayName.c_str() , bSel ) )
				{
					m_iSelectedMusicIdx = Skin.m_ID;

					pManager->RequestMusicKit( Skin.m_ID );
				}
			}
		}

		ImGui::NewLine();

		if ( ImGui::Button( "Reset" , ImVec2( 100.f * m_fUIScale , 28.f * m_fUIScale ) ) )
			pManager->RequestRemoveMusicKit();
	}

	ImGui::EndChild();
}

auto CAndromedaMenu::RenderMiscPanel() -> void
{
	ImGui::SeparatorText( "Movement" );

	Checkbox( "Bunnyhop" , Settings::Misc::Bunnyhop );
	Checkbox( "No Flash" , Settings::Misc::NoFlash );

	ImGui::SeparatorText( "Camera" );

	Checkbox( "FOV Changer" , Settings::Misc::FOVChanger );

	if ( Settings::Misc::FOVChanger )
		SliderInt( "FOV" , Settings::Misc::FOV , 70 , 120 );

	ImGui::SeparatorText( "Overlays" );

	Checkbox( "Watermark" , Settings::Misc::Watermark );
	Checkbox( "Spectator List" , Settings::Misc::SpectatorList );

	ImGui::SeparatorText( "Combat Feedback" );

	Checkbox( "Hitmarker" , Settings::Misc::Hitmarker );
	Checkbox( "Hit Sound" , Settings::Misc::HitSound );

	ImGui::SeparatorText( "Triggerbot" );

	Checkbox( "Triggerbot" , Settings::Triggerbot::Active );

	if ( Settings::Triggerbot::Active )
	{
		const char* TriggerModeItems[] =
		{
			"Hold Key" , "Always" , "Toggle"
		};

		Combo( "Mode" , Settings::Triggerbot::Mode , TriggerModeItems , IM_ARRAYSIZE( TriggerModeItems ) );

		static const char* TriggerKeyItems[] =
		{
			"Alt" , "Shift" , "Ctrl" , "Mouse 4" , "Mouse 5" , "Q" , "E" , "F" , "X" , "C" , "V" , "B" , "Space"
		};

		static const int TriggerKeys[] =
		{
			VK_MENU , VK_SHIFT , VK_CONTROL , 0x04 , 0x05 , 0x51 , 0x45 , 0x46 , 0x58 , 0x43 , 0x56 , 0x42 , VK_SPACE
		};

		int iKeyIdx = 0;

		for ( int i = 0; i < IM_ARRAYSIZE( TriggerKeys ); i++ )
		{
			if ( TriggerKeys[ i ] == Settings::Triggerbot::Key )
			{
				iKeyIdx = i;
				break;
			}
		}

		if ( Combo( "Key" , iKeyIdx , TriggerKeyItems , IM_ARRAYSIZE( TriggerKeyItems ) ) )
			Settings::Triggerbot::Key = TriggerKeys[ iKeyIdx ];

		SliderInt( "Delay (ms)" , Settings::Triggerbot::Delay , 0 , 300 );
		SliderInt( "Hold Time (ms)" , Settings::Triggerbot::HoldTime , 0 , 200 );

		ImGui::Separator();

		Checkbox( "Nur gescoped (Sniper)" , Settings::Triggerbot::ScopedOnly );
		Checkbox( "Teammates ignorieren" , Settings::Triggerbot::IgnoreTeammates );
		Checkbox( "Fadenkreuz-Indikator" , Settings::Triggerbot::DrawIndicator );

		ImGui::Separator();

		Checkbox( "Kopf" , Settings::Triggerbot::Hitbox_Head );
		Checkbox( "Brust" , Settings::Triggerbot::Hitbox_Chest );
		Checkbox( "Bauch" , Settings::Triggerbot::Hitbox_Stomach );
		Checkbox( "Arme" , Settings::Triggerbot::Hitbox_Arms );
		Checkbox( "Beine" , Settings::Triggerbot::Hitbox_Legs );
	}
}

auto CAndromedaMenu::RenderConfigPanel() -> void
{
	ImGui::SeparatorText( "Menu" );

	SliderInt( "Menu Alpha" , Settings::Menu::MenuAlpha , 100 , 255 );

	const char* MenuStyleItems[] =
	{
		"Indigo" , "Vermillion" , "Classic Steam"
	};

	if ( Combo( "Menu Style" , Settings::Menu::MenuStyle , MenuStyleItems , IM_ARRAYSIZE( MenuStyleItems ) ) )
		GetAndromedaGUI()->UpdateStyle();

	ImGui::SeparatorText( "Skinchanger" );

	ImGui::TextColored( ImVec4( 1.f , 1.f , 1.f , 0.4f ) , "%s" , "The skin changer now applies only the skins you configure per weapon." );

	if ( ImGui::Button( "Clear All Skins" , ImVec2( 150.f * m_fUIScale , 28.f * m_fUIScale ) ) )
		GetInventoryItemsManager()->ClearAllSelections();
}

auto CAndromedaMenu::Checkbox( const char* szLabel , bool& bValue ) -> bool
{
	return ImGui::Checkbox( szLabel , &bValue );
}

auto CAndromedaMenu::SliderInt( const char* szLabel , int& iValue , int iMin , int iMax , const char* szFormat ) -> bool
{
	return ImGui::SliderInt( szLabel , &iValue , iMin , iMax , szFormat );
}

auto CAndromedaMenu::SliderFloat( const char* szLabel , float& fValue , float fMin , float fMax , const char* szFormat ) -> bool
{
	return ImGui::SliderFloat( szLabel , &fValue , fMin , fMax , szFormat );
}

auto CAndromedaMenu::Combo( const char* szLabel , int& iValue , const char* Items[] , int iItemsCount ) -> bool
{
	return ImGui::Combo( szLabel , &iValue , Items , iItemsCount );
}

auto CAndromedaMenu::ColorEdit( const char* szLabel , float* flColor ) -> bool
{
	return ImGui::ColorEdit4( szLabel , flColor , ImGuiColorEditFlags_AlphaBar | ImGuiColorEditFlags_NoInputs );
}

auto GetAndromedaMenu() -> CAndromedaMenu*
{
	return &g_CAndromedaMenu;
}
