#include "IMP_SkillTraits.h"

#include "Button_Sound_Control.h"
#include "Button_System.h"
#include "CharProfile.h"
#include "Cursors.h"
#include "Debug.h"
#include "Directories.h"
#include "Font.h"
#include "Font_Control.h"
#include "IMPVideoObjects.h"
#include "IMP_Compile_Character.h"
#include "IMP_MainPage.h"
#include "Laptop.h"
#include "MouseSystem.h"
#include "Soldier_Profile_Type.h"
#include "Text.h"
#include "VObject.h"
#include "VSurface.h"
#include "Video.h"
#include "WordWrap.h"

#include <algorithm>
#include <map>

enum ImpSkillTrait
{
	IMP_SKILL_TRAITS__LOCKPICK,
	IMP_SKILL_TRAITS__HAND_2_HAND,
	IMP_SKILL_TRAITS__ELECTRONICS,
	IMP_SKILL_TRAITS__NIGHT_OPS,
	IMP_SKILL_TRAITS__THROWING,
	IMP_SKILL_TRAITS__TEACHING,
	IMP_SKILL_TRAITS__HEAVY_WEAPONS,
	IMP_SKILL_TRAITS__AUTO_WEAPONS,
	IMP_SKILL_TRAITS__STEALTHY,
	IMP_SKILL_TRAITS__AMBIDEXTROUS,
	IMP_SKILL_TRAITS__KNIFING,
	IMP_SKILL_TRAITS__ROOFTOP_SNIPING,
	IMP_SKILL_TRAITS__CAMO,
	IMP_SKILL_TRAITS__MARTIAL_ARTS,
	IMP_SKILL_TRAITS__NONE,

	IMP_SKILL_TRAITS__NUMBER_SKILLS,
};

// maps from IMP_SKILL_TRAITS to SkillTrait (see Soldier_Profile_Type.h)
std::map<ImpSkillTrait, SkillTrait> skillTraitsMapping = {
	{ IMP_SKILL_TRAITS__LOCKPICK,        LOCKPICKING },
	{ IMP_SKILL_TRAITS__HAND_2_HAND,     HANDTOHAND },
	{ IMP_SKILL_TRAITS__ELECTRONICS,     ELECTRONICS },
	{ IMP_SKILL_TRAITS__NIGHT_OPS,       NIGHTOPS },
	{ IMP_SKILL_TRAITS__THROWING,        THROWING },
	{ IMP_SKILL_TRAITS__TEACHING,        TEACHING },
	{ IMP_SKILL_TRAITS__HEAVY_WEAPONS,   HEAVY_WEAPS },
	{ IMP_SKILL_TRAITS__AUTO_WEAPONS,    AUTO_WEAPS },
	{ IMP_SKILL_TRAITS__STEALTHY,        STEALTHY },
	{ IMP_SKILL_TRAITS__AMBIDEXTROUS,    AMBIDEXT },
	{ IMP_SKILL_TRAITS__KNIFING,         KNIFING },
	{ IMP_SKILL_TRAITS__ROOFTOP_SNIPING, ONROOF },
	{ IMP_SKILL_TRAITS__CAMO,            CAMOUFLAGED },
	{ IMP_SKILL_TRAITS__MARTIAL_ARTS,    MARTIALARTS }
};

//*******************************************************************
//
// Local Defines
//
//*******************************************************************

#define			IMP_SKILL_TRAIT__TITLE_FONT				FONT14ARIAL

#define			IMP_SKILL_TRAIT__FONT							FONT12ARIAL
#define			IMP_SKILL_TRAIT__COLOR						FONT_MCOLOR_WHITE



enum
{
	IMP_SKILL_TRAIT__TITLE_TEXT=IMP_SKILL_TRAITS__NUMBER_SKILLS,
};



#define	IMP_SKILL_TRAIT__LEFT_COLUMN_START_X								( LAPTOP_SCREEN_UL_X + 15 )
#define	IMP_SKILL_TRAIT__LEFT_COLUMN_START_Y								( LAPTOP_SCREEN_WEB_UL_Y + 40 )

#define	IMP_SKILL_TRAIT__RIGHT_COLUMN_START_X								( IMP_SKILL_TRAIT__LEFT_COLUMN_START_X + 241 )
#define	IMP_SKILL_TRAIT__RIGHT_COLUMN_START_Y								IMP_SKILL_TRAIT__LEFT_COLUMN_START_Y

#define	IMP_SKILL_TRAIT__SPACE_BTN_BUTTONS									38

#define	IMP_SKILL_TRAIT__SKILL_TRAIT_TO_START_RIGHT_COL			6

#define	IMP_SKILL_TRAIT__NONE_BTN_LOC_X											( LAPTOP_SCREEN_UL_X + 136 )

#define	IMP_SKILL_TRAIT__TEXT_OFFSET_X											65
#define	IMP_SKILL_TRAIT__TEXT_OFFSET_Y											12

#define	IMP_SKILL_TRAIT__TITLE_X														LAPTOP_SCREEN_UL_X
#define	IMP_SKILL_TRAIT__TITLE_Y														56
#define	IMP_SKILL_TRAIT__TITLE_WIDTH												( LAPTOP_SCREEN_LR_X - LAPTOP_SCREEN_UL_X )

#define	IMP_SKILL_TRAIT__GREY_BOX_OFFSET_X									5
#define	IMP_SKILL_TRAIT__GREY_BOX_OFFSET_Y									7


//*******************************************************************
//
// Global Variables
//
//*******************************************************************

BOOLEAN gfIST_Redraw=FALSE;

BOOLEAN	gfSkillTraitQuestions[ IMP_SKILL_TRAITS__NUMBER_SKILLS ];

// these are the buttons for the questions
GUIButtonRef giIMPSkillTraitAnswerButton[ IMP_SKILL_TRAITS__NUMBER_SKILLS ];
BUTTON_PICS* giIMPSkillTraitAnswerButtonImage[ IMP_SKILL_TRAITS__NUMBER_SKILLS ];

// this is the Done  buttons
GUIButtonRef giIMPSkillTraitFinsihButton;
BUTTON_PICS* giIMPSkillTraitFinsihButtonImage;

#define	IST__NUM_SELECTABLE_TRAITS				2
INT8	gbLastSelectedTraits[ IST__NUM_SELECTABLE_TRAITS ];

//image handle
SGPVObject* guiIST_GreyGoldBox;

//*******************************************************************
//
// Function Prototypes
//
//*******************************************************************

void		BtnIMPSkillTraitAnswerCallback(GUI_BUTTON *btn,UINT32 reason);
void		BtnIMPSkillTraitFinishCallback(GUI_BUTTON *btn,UINT32 reason);
void		AddImpSkillTraitButtons();
void		HandleSkillTraitButtonStates( );
void		HandleIMPSkillTraitAnswers( UINT32 uiSkillPressed, BOOLEAN fResetAllButtons );
void		IMPSkillTraitDisplaySkills();
INT8		CountNumSkillStraitsSelected( BOOLEAN fIncludeNoneSkill );
BOOLEAN ShouldTraitBeSkipped( UINT32 uiTrait );
void		AddSelectedSkillsToSkillsList();
void		HandleLastSelectedTraits( INT8 bNewTrait );
BOOLEAN CameBackToSpecialtiesPageButNotFinished();
//ppp

//*******************************************************************
//
// Functions
//
//*******************************************************************



void EnterIMPSkillTrait( void )
{
	//clear any existing skills
	ResetSkillsAttributesAndPersonality();

	//add the skill trait buttons
	AddImpSkillTraitButtons();


	// load the stats graphic and add it
	guiIST_GreyGoldBox = AddVideoObjectFromFile("sti/laptop/SkillTraitSmallGreyIdent.sti");
	giIMPSkillTraitFinsihButtonImage = LoadButtonImage(LAPTOPDIR "/button_5.sti", -1, 0, -1, 1, -1);
	giIMPSkillTraitFinsihButton = CreateIconAndTextButton(giIMPSkillTraitFinsihButtonImage, pImpButtonText[11], FONT12ARIAL,
		FONT_WHITE, DEFAULT_SHADOW,
		FONT_WHITE, DEFAULT_SHADOW,
		LAPTOP_SCREEN_UL_X + (350), LAPTOP_SCREEN_WEB_UL_Y + (340), MSYS_PRIORITY_HIGH,
		(GUI_CALLBACK)BtnIMPSkillTraitFinishCallback);


	giIMPSkillTraitFinsihButton->SetCursor(CURSOR_WWW);

	//if we are not DONE and are just reviewing
	if( iCurrentProfileMode != 5 )
	{
		//Have the NONE trait initially selected
		gfSkillTraitQuestions[ IMP_SKILL_TRAITS__NONE ] = TRUE;
	}

	HandleSkillTraitButtonStates( );

	//reset last selecterd trait
	std::fill_n(gbLastSelectedTraits, IST__NUM_SELECTABLE_TRAITS, -1);
}


void RenderIMPSkillTrait( void )
{
	//render the metal background graphic
	RenderProfileBackGround();

	IMPSkillTraitDisplaySkills();
}


void ExitIMPSkillTrait( void )
{
	INT32 iCnt;

	DeleteVideoObject( guiIST_GreyGoldBox );

	//remove the skill buttons
	for(iCnt = 0; iCnt < IMP_SKILL_TRAITS__NUMBER_SKILLS; iCnt++)
	{
		//if there is a button allocated
		if (giIMPSkillTraitAnswerButton[iCnt] != NULL)
		{
			RemoveButton(giIMPSkillTraitAnswerButton[ iCnt ] );
			UnloadButtonImage(giIMPSkillTraitAnswerButtonImage[ iCnt ] );
		}
	}

	RemoveButton( giIMPSkillTraitFinsihButton );
	UnloadButtonImage( giIMPSkillTraitFinsihButtonImage );
}


void HandleIMPSkillTrait( void )
{
	if( gfIST_Redraw )
	{
		RenderIMPSkillTrait( );
		gfIST_Redraw = FALSE;
	}

  InvalidateRegion(LAPTOP_SCREEN_UL_X,LAPTOP_SCREEN_WEB_UL_Y,LAPTOP_SCREEN_LR_X,LAPTOP_SCREEN_WEB_LR_Y);
}

void AddImpSkillTraitButtons()
{
	INT32 iCnt = 0;
	UINT16 usPosX, usPosY;

	usPosX = IMP_SKILL_TRAIT__LEFT_COLUMN_START_X;
	usPosY = IMP_SKILL_TRAIT__LEFT_COLUMN_START_Y;

	for(iCnt = 0; iCnt < IMP_SKILL_TRAITS__NUMBER_SKILLS; iCnt++)
	{
		//reset
		giIMPSkillTraitAnswerButton[iCnt] = {};

		//if we are not DONE and are just reviewing
		if( iCurrentProfileMode != 5 )
		{
			gfSkillTraitQuestions[ iCnt ] = FALSE;
		}

		//if the merc is a FEMALE, skip this skill cause there isnt any fenmal martial artists
		if( ShouldTraitBeSkipped( iCnt ) )
		{
			usPosY += IMP_SKILL_TRAIT__SPACE_BTN_BUTTONS;

			//if its the none button
			if( iCnt == IMP_SKILL_TRAITS__NONE-1 )
			{
				usPosX = IMP_SKILL_TRAIT__NONE_BTN_LOC_X;
			}
			continue;
		}

		if ( iCnt == 0 )
			giIMPSkillTraitAnswerButtonImage[ iCnt ] = LoadButtonImage(LAPTOPDIR "/button_6.sti", -1, 0, -1, 1, -1);
		else
			giIMPSkillTraitAnswerButtonImage[ iCnt ] =  UseLoadedButtonImage( giIMPSkillTraitAnswerButtonImage[ 0 ], -1,0,-1,1,-1 );


		giIMPSkillTraitAnswerButton[iCnt] = QuickCreateButtonToggle(giIMPSkillTraitAnswerButtonImage[iCnt], usPosX, usPosY,
									MSYS_PRIORITY_HIGHEST - 3,
									(GUI_CALLBACK)BtnIMPSkillTraitAnswerCallback);
		//Set the button data
		giIMPSkillTraitAnswerButton[iCnt]->SetUserData(iCnt);
		giIMPSkillTraitAnswerButton[iCnt]->SetCursor(CURSOR_WWW);

		//Get rid of playing the button sound, it will be handled here
		giIMPSkillTraitAnswerButton[iCnt]->ubSoundSchemeID = 0;

		//Determine the next x location
		if( iCnt < IMP_SKILL_TRAIT__SKILL_TRAIT_TO_START_RIGHT_COL )
			usPosX = IMP_SKILL_TRAIT__LEFT_COLUMN_START_X;
		else
			usPosX = IMP_SKILL_TRAIT__RIGHT_COLUMN_START_X;

		//Determine the next Y location
		if( iCnt == IMP_SKILL_TRAIT__SKILL_TRAIT_TO_START_RIGHT_COL )
			usPosY = IMP_SKILL_TRAIT__RIGHT_COLUMN_START_Y;
		else
			usPosY += IMP_SKILL_TRAIT__SPACE_BTN_BUTTONS;

		//if its the none button
		if( iCnt == IMP_SKILL_TRAITS__NONE-1 )
		{
			usPosX = IMP_SKILL_TRAIT__NONE_BTN_LOC_X;
		}
	}
}


void BtnIMPSkillTraitAnswerCallback(GUI_BUTTON *btn,UINT32 reason)
{
	// btn callback for IMP personality quiz answer button
	if (!(btn->uiFlags & BUTTON_ENABLED))
		return;

	if( reason & MSYS_CALLBACK_REASON_POINTER_DWN )
	{
//		btn->uiFlags|=(BUTTON_CLICKED_ON);

		INT32 iSkillTrait = btn->GetUserData();

		HandleIMPSkillTraitAnswers( iSkillTrait, FALSE );
	}
}
void HandleIMPSkillTraitAnswers( UINT32 uiSkillPressed, BOOLEAN fResetAllButtons )
{
	UINT32 uiCnt;

	//if we are DONE and are just reviewing
	if( iCurrentProfileMode == 5 )
	{
		return;
	}

	//if we are to reset all the buttons
	if( fResetAllButtons )
	{
		//loop through all the skill and reset them
		for( uiCnt=0; uiCnt<IMP_SKILL_TRAITS__NUMBER_SKILLS; uiCnt++ )
		{
			gfSkillTraitQuestions[ uiCnt ] = FALSE;
		}
		return;
	}

	//make sure its a valid skill
	if (uiSkillPressed >= IMP_SKILL_TRAITS__NUMBER_SKILLS)
	{
		Assert( 0 );
		return;
	}


	//if its allready set
	if( gfSkillTraitQuestions[ uiSkillPressed ] )
	{
		//dont need to do anything
		return;
	}

	HandleLastSelectedTraits( (INT8)uiSkillPressed );


	//Set the skill
	gfSkillTraitQuestions[ uiSkillPressed ] = TRUE;

	//if the NONE trait was selected, clear the rest of the buttons
	if( uiSkillPressed == IMP_SKILL_TRAITS__NONE )
	{
		//reset all the traits
		HandleIMPSkillTraitAnswers( 0, TRUE );

		gfSkillTraitQuestions[ IMP_SKILL_TRAITS__NONE ] = TRUE;
	}


	//make sure the none skill is NOT selected if we select anything else
	if( uiSkillPressed != IMP_SKILL_TRAITS__NONE )
	{
		gfSkillTraitQuestions[ IMP_SKILL_TRAITS__NONE ] = FALSE;
	}

	//Play the button sound
	if( gfSkillTraitQuestions[ uiSkillPressed ] )
	{
		PlayButtonSound( giIMPSkillTraitAnswerButton[ uiSkillPressed ], BUTTON_SOUND_CLICKED_ON );
	}
	else
	{
		PlayButtonSound( giIMPSkillTraitAnswerButton[ uiSkillPressed ], BUTTON_SOUND_CLICKED_OFF );
	}

	//update buttons
	HandleSkillTraitButtonStates( );

	//redraw the screen
	gfIST_Redraw = TRUE;
}

INT8	CountNumSkillStraitsSelected( BOOLEAN fIncludeNoneSkill )
{
	UINT32	uiCnt;
	INT8	iNumberSkills=0;
	UINT32	uiUpperLimit;

	if( fIncludeNoneSkill )
	{
		uiUpperLimit = IMP_SKILL_TRAITS__NUMBER_SKILLS;
	}
	else
	{
		uiUpperLimit = IMP_SKILL_TRAITS__NONE;
	}

	for( uiCnt=0; uiCnt < uiUpperLimit; uiCnt++ )
	{
		//if the skill is selected ( ie depressed )
		if( gfSkillTraitQuestions[ uiCnt ] )
		{
			iNumberSkills++;
		}
	}

	return( iNumberSkills );
}


void HandleSkillTraitButtonStates( )
{
	UINT32 uiCnt;

	for( uiCnt=0; uiCnt<IMP_SKILL_TRAITS__NUMBER_SKILLS; uiCnt++ )
	{
			//if the merc is a FEMALE, skip this skill cause there isnt any fenmal martial artists
		if( ShouldTraitBeSkipped( uiCnt ) )
		{
			continue;
		}

		//if the skill is selected ( ie depressed )
		if( gfSkillTraitQuestions[ uiCnt ] )
		{
			giIMPSkillTraitAnswerButton[uiCnt]->uiFlags |= BUTTON_CLICKED_ON;
		}
		else
		{
			giIMPSkillTraitAnswerButton[uiCnt]->uiFlags &= ~BUTTON_CLICKED_ON;
		}
	}
}

void IMPSkillTraitDisplaySkills()
{
	UINT32 uiCnt;
	UINT16 usPosX, usPosY;
	UINT16 usBoxPosX, usBoxPosY;

	//Display the title
	DrawTextToScreen(gzIMPSkillTraitsText[IMP_SKILL_TRAIT__TITLE_TEXT],
		IMP_SKILL_TRAIT__TITLE_X, IMP_SKILL_TRAIT__TITLE_Y, IMP_SKILL_TRAIT__TITLE_WIDTH, IMP_SKILL_TRAIT__TITLE_FONT,
		IMP_SKILL_TRAIT__COLOR, FONT_MCOLOR_BLACK, CENTER_JUSTIFIED
	);
	// Stats
	usPosX = IMP_SKILL_TRAIT__LEFT_COLUMN_START_X + IMP_SKILL_TRAIT__TEXT_OFFSET_X;
	usPosY = IMP_SKILL_TRAIT__LEFT_COLUMN_START_Y + IMP_SKILL_TRAIT__TEXT_OFFSET_Y;

	for( uiCnt=0; uiCnt<IMP_SKILL_TRAITS__NUMBER_SKILLS; uiCnt++ )
	{
		usBoxPosX = usPosX - IMP_SKILL_TRAIT__GREY_BOX_OFFSET_X;
		usBoxPosY = usPosY - IMP_SKILL_TRAIT__GREY_BOX_OFFSET_Y;

		//if the merc is a FEMALE, skip this skill cause there isnt any fenmal martial artists
		if( ShouldTraitBeSkipped( uiCnt ) )
		{
			//if its the none button
			if( uiCnt == IMP_SKILL_TRAITS__NONE-1 )
			{
				usPosX = IMP_SKILL_TRAIT__NONE_BTN_LOC_X + IMP_SKILL_TRAIT__TEXT_OFFSET_X;
				usPosY += IMP_SKILL_TRAIT__SPACE_BTN_BUTTONS;
			}
			continue;
		}

		//if the trait is selected
		if( gfSkillTraitQuestions[ uiCnt ] )
		{
			//Display the gold background box
			BltVideoObject(FRAME_BUFFER, guiIST_GreyGoldBox, 1, usBoxPosX, usBoxPosY);
		}
		else
		{
			//Display the grey background box
			BltVideoObject(FRAME_BUFFER, guiIST_GreyGoldBox, 0, usBoxPosX, usBoxPosY);
		}

		//draw the text to the screenx
		DrawTextToScreen(gzIMPSkillTraitsText[uiCnt], usPosX, usPosY, 0, IMP_SKILL_TRAIT__FONT, IMP_SKILL_TRAIT__COLOR, FONT_MCOLOR_BLACK, LEFT_JUSTIFIED);

		//Determine the next x location
		if( uiCnt < IMP_SKILL_TRAIT__SKILL_TRAIT_TO_START_RIGHT_COL )
			usPosX = IMP_SKILL_TRAIT__LEFT_COLUMN_START_X + IMP_SKILL_TRAIT__TEXT_OFFSET_X;
		else
			usPosX = IMP_SKILL_TRAIT__RIGHT_COLUMN_START_X + IMP_SKILL_TRAIT__TEXT_OFFSET_X;

		//Determine the next Y location
		if( uiCnt == IMP_SKILL_TRAIT__SKILL_TRAIT_TO_START_RIGHT_COL )
			usPosY = IMP_SKILL_TRAIT__RIGHT_COLUMN_START_Y + IMP_SKILL_TRAIT__TEXT_OFFSET_Y;
		else
			usPosY += IMP_SKILL_TRAIT__SPACE_BTN_BUTTONS;

		//if its the none button
		if( uiCnt == IMP_SKILL_TRAITS__NONE-1 )
		{
			usPosX = IMP_SKILL_TRAIT__NONE_BTN_LOC_X + IMP_SKILL_TRAIT__TEXT_OFFSET_X;
		}
	}
}


void BtnIMPSkillTraitFinishCallback(GUI_BUTTON *btn,UINT32 reason)
{
	// btn callback for IMP personality quiz answer button
	if (!(btn->uiFlags & BUTTON_ENABLED))
		return;

	if( reason & MSYS_CALLBACK_REASON_POINTER_DWN )
	{
		btn->uiFlags|=(BUTTON_CLICKED_ON);

		//if we are just reviewing the page
		if( iCurrentProfileMode == 5 )
		{
			//go back tot he done screen
			iCurrentImpPage = IMP_FINISH;
		}
		else
		{
			iCurrentImpPage = IMP_MAIN_PAGE;

			if( CameBackToSpecialtiesPageButNotFinished() )
			{
			}
			else
			{
				//We are finished on this page
				iCurrentProfileMode = 2;
			}
		}
	}
}


BOOLEAN CameBackToSpecialtiesPageButNotFinished()
{
	//if we are in a page that comes after this one
	return iCurrentProfileMode == 2;
}

INT8	DoesPlayerHaveExtraAttibutePointsToDistributeBasedOnSkillSelection()
{
	INT8		bExtraPoints=10;
	INT8		bNumSkills=0;

	//Count the number of skills selected
	bNumSkills = CountNumSkillStraitsSelected( FALSE );

	//if there NONE selected
	if( bNumSkills == 0 )
	{
		bExtraPoints = 10;
	}

	//if there is 1 trait selected
	else if( bNumSkills == 1 )
	{
		//if the trait is not the ones you cant be expert in )
		if( gfSkillTraitQuestions[ IMP_SKILL_TRAITS__ELECTRONICS ] ||
				gfSkillTraitQuestions[ IMP_SKILL_TRAITS__AMBIDEXTROUS  ] ||
				gfSkillTraitQuestions[ IMP_SKILL_TRAITS__CAMO ] )
		{
			bExtraPoints = 5;
		}
		else
		{
			bExtraPoints = 0;
		}
	}

	//else both traits selected
	else
	{
		bExtraPoints = 0;
	}

	return( bExtraPoints );
}



BOOLEAN ShouldTraitBeSkipped( UINT32 uiTrait )
{
	return uiTrait == IMP_SKILL_TRAITS__MARTIAL_ARTS && !fCharacterIsMale;
}


void AddSelectedSkillsToSkillsList()
{
	UINT8	uiCnt;

	//loop through all the buttons and reset them
	for( uiCnt=0; uiCnt<IMP_SKILL_TRAITS__NONE; uiCnt++ )
	{
		//if the trait is selected
		if( gfSkillTraitQuestions[ uiCnt ] )
		{
			//switch on the trait, and add it to the list
			auto impTrait = static_cast<ImpSkillTrait>(uiCnt);
			auto skillTrait = skillTraitsMapping.at(impTrait);
			AddSkillToSkillList(skillTrait);
		}
	}
}


void HandleLastSelectedTraits( INT8 bNewTrait )
{
	//if there are none selected
	if( gbLastSelectedTraits[ 0 ] == -1 )
	{
		gbLastSelectedTraits[ 0 ] = bNewTrait;
	}

	//if the second one is not selected
	else if( gbLastSelectedTraits[ 1 ] == -1 )
	{
		gbLastSelectedTraits[ 1 ] = gbLastSelectedTraits[ 0 ];
		gbLastSelectedTraits[ 0 ] = bNewTrait;
	}

	else
	{
		//unselect old trait
		gfSkillTraitQuestions[ gbLastSelectedTraits[ 1 ] ] = FALSE;

		gbLastSelectedTraits[ 1 ] = gbLastSelectedTraits[ 0 ];
		gbLastSelectedTraits[ 0 ] = bNewTrait;
	}
}
