/* Player - Accepts input, knocks down TapNotes that were stepped on, and keeps score for the player. */
// LIFT NOTE CODE:	NoteDataUtil.cpp, NoteDataUtil.h, NoteTypes.cpp, NoteTypes.h, ScreenEdit.cpp,
//					NoteDisplay.cpp, NoteDisplay.h, PlayerOptions.cpp, PlayerOptions.h,
//					PaneDisplay.cpp, PaneDisplay.h, NoteData.cpp, NoteData.h, GameState.cpp,
//					ScreenEvaluation.cpp, NoteDataWithScoring.cpp, NoteDataWithScoring.h, Steps.cpp,
//					GameConstantsAndTypes.h, NoteField.cpp, ScreenGameplay.cpp, Player.cpp, Player.h,
//					ScreenEvaluation.h, Profile.cpp, Profile.h, ProfileManager.cpp, ProfileManager.h
// ATTACK MINES CODE: Player.cpp, Player.h, PlayerOptions.cpp, PlayerOptions.h, PrefsManager.cpp,
//						PrefsManager.h, GameState.h, SongManager.cpp, SongManager.h
// RANDOM ATTACK CODE: Player.cpp, Player.h, PlayerOptions.cpp, PlayerOptions.h, PrefsManager.cpp,
//						PrefsManager.h, GameState.h, SongManager.cpp, SongManager.h
// ROLL NOTE CODE:	ScreenEdit.cpp, ScreenEdit.h, ScreenEvaluation.cpp, ScreenEvaluation.h,
//					ScreenGameplay.cpp, CatalogXml.cpp, CodeDetector.cpp, CodeDetector.h,
//					GameConstantsAndTypes.cpp, GameConstantsAndTypes.h, HighScore.cpp, HighScore.h,
//					NoteData.cpp, NoteData.h, NoteDataUtil.cpp, NoteDataUtil.h, NoteTypes.cpp,
//					NoteTypes.h, NoteDataWithScoring.cpp, NoteDataWithScoring.h, PlayerOptions.cpp,
//					PlayerOptions.h, Profile.cpp, Profile.h, RadarValues.cpp, ScoreKeeper.h,
//					ScoreKeeperMAX2.cpp, ScoreKeeperMAX2.h, SongUtil.cpp, StageStats.cpp,
//					StageStats.h, StepsUtil.cpp, OptionIconRow.cpp, PaneDisplay.cpp, PaneDisplay.h,
//					CombinedLifeMeter.h, CombinedLifeMeterTug.cpp, CombinedLifeMeterTug.h, LifeMeter.h,
//					GhostArrowRow.cpp, GhostArrowRow.h, RollGhostArrow.cpp, RollGhostArrow.h,
//					LifeMeterBar.cpp, LifeMeterBar.h, LifeMeterBattery.cpp, LifeMeterBattery.h,
//					NoteDisplay.cpp, NoteDisplay.h, NoteField.cpp, NoteField.h, Player.cpp, Player.h,
//					RollJudgment.cpp, RollJudgment.h, GameState.cpp, ProfileManager.cpp,
//					ProfileManager.h, HoldJudgment.cpp
// JUDGMENT LABELS PER DIFFICULTY - Judgment.cpp, Judgment.h, Player.cpp, Player.h, ThemeManager.cpp, Sprite.cpp
//									Sprite.h, ScreenGameplay.cpp, ScreenEdit.cpp. GameState.h

#ifndef PLAYER_H
#define PLAYER_H

#include "PrefsManager.h"	// for GameplayStatistics
#include "Sprite.h"
#include "BitmapText.h"

#include "ActorFrame.h"
#include "RandomSample.h"
#include "Judgment.h"
#include "HoldJudgment.h"
#include "RollJudgment.h"
#include "Combo.h"
#include "NoteDataWithScoring.h"
#include "ArrowBackdrop.h"
#include "RageTimer.h"
#include "ProTimingDisplay.h"
#include "RageSound.h"
#include "AttackDisplay.h"
#include "NoteField.h"

class ScoreDisplay;
class LifeMeter;
class CombinedLifeMeter;
class ScoreKeeper;
class Inventory;

#define	SAMPLE_COUNT			16
#define CPU_ROLL_REHIT_LIFE		0.25
#define CPU_ROLL_LETGO_LIFE		0.7


class PlayerMinus : public NoteDataWithScoring, public ActorFrame
{
public:
	PlayerMinus();
	~PlayerMinus();

	virtual void Update( float fDeltaTime );
	virtual void DrawPrimitives();

	void InitJudgment( PlayerNumber pn, Difficulty dc );
	void Load( PlayerNumber player_no, const NoteData* pNoteData, LifeMeter* pLM, CombinedLifeMeter* pCombinedLM, ScoreDisplay* pScoreDisplay, ScoreDisplay* pSecondaryScoreDisplay, Inventory* pInventory, ScoreKeeper* pPrimaryScoreKeeper, ScoreKeeper* pSecondaryScoreKeeper, NoteField* pNoteField );
	void CrossedRow( int iNoteRow );
	void CrossedMineRow( int iNoteRow );
	void Step( int col, RageTimer tm );
	void Release( int col, RageTimer tm );
	void RandomiseNotes( int iNoteRow );
	void FadeToFail();
	int GetDancingCharacterState() const { return m_iDCState; };
	void SetCharacterState(int iDCState) { m_iDCState = iDCState; };
	void ApplyWaitingTransforms();

	bool m_bActiveRandomAttack;
	float m_fActiveRandomAttackStart;

	CString ApplyRandomAttack();
	map<unsigned,CString> m_sAttackMap;

	static float GetMaxStepDistanceSeconds();

protected:
	void UpdateTapNotesMissedOlderThan( float fMissIfOlderThanThisBeat );
	void OnRowCompletelyJudged( int iStepIndex, bool bSteppedEarly, bool bHolds );
	void HandleTapRowScore( unsigned row );
	void HandleTapRowScoreCheckpoint( TapNoteScore score );
	void HandleHoldScore( HoldNoteScore holdScore, TapNoteScore tapScore );
	void HandleRollScore( RollNoteScore rollScore, TapNoteScore tapScore );
	void HandleAutosync(float fNoteOffset);
	void DrawTapJudgments();
	void DrawHoldJudgments();
	void DrawRollJudgments();

	int GetClosestNoteDirectional( int col, float fBeat, float fMaxBeatsAhead, int iDirection ) const;
	int GetClosestNote( int col, float fBeat, float fMaxBeatsAhead, float fMaxBeatsBehind ) const;

	PlayerNumber	m_PlayerNumber;
	float			m_fNoteFieldHeight;

	float			m_fOffset[SAMPLE_COUNT]; // for AutoSync
	int				m_iOffsetSample;

	ArrowBackdrop	m_ArrowBackdrop;
	NoteField*		m_pNoteField;

	HoldJudgment	m_HoldJudgment[MAX_NOTE_TRACKS];
	RollJudgment	m_RollJudgment[MAX_NOTE_TRACKS];

	Judgment		m_Judgment;
	ProTimingDisplay m_ProTimingDisplay;
	
	Combo			m_Combo;

	AttackDisplay	m_AttackDisplay;

	int m_iDCState;
	LifeMeter*		m_pLifeMeter;
	CombinedLifeMeter*		m_pCombinedLifeMeter;
	ScoreDisplay*	m_pScoreDisplay;
	ScoreDisplay*	m_pSecondaryScoreDisplay;
	ScoreKeeper*	m_pPrimaryScoreKeeper;
	ScoreKeeper*	m_pSecondaryScoreKeeper;
	Inventory*		m_pInventory;

	int				m_iRowLastCrossed;
	int				m_iMineRowLastCrossed;
	int				m_iRowOfNextCheckpoint;

	int				m_iNumNotesThisCheckpoint;
	int				m_iNumHoldsThisCheckpoint;
	int				m_iNumNotesNextCheckpoint;
	int				m_iNumHoldsNextCheckpoint;
	int				m_iNumHitNotesForCheckpoint;

	int				m_iLastCheckpointRow;

	bool			m_bNeedCheckpoint;
	bool			m_bPrepareNextCheckpoint;
	bool			m_bInitialCheckpointSet;
	bool			m_bCheckpointHoldHead;
	bool			m_bMissedAHoldCheckpoint;

	// This is used only by hold checkpoint
	map<RowTrack,bool> m_bHoldColumnButtonDown;		// true if button has been held down on at least part of the hold

	// This is only used for RollNotes, nothing else
	map<RowTrack,bool> m_bMustRelease;		// true if button is being held down
	map<RowTrack,int> m_iAutoReleaseCount;	// for proper AutoPlay behaviour

	RageSound		m_soundMine;
	RageSound		m_soundAttackLaunch;
	RageSound		m_soundAttackEnding;

	int				m_iLastUsedAttacks[5];	// Store the last five random/mine attacks
};

class Player : public PlayerMinus
{
public:
	void Load( PlayerNumber player_no, const NoteData* pNoteData, LifeMeter* pLM, CombinedLifeMeter* pCombinedLM, ScoreDisplay* pScoreDisplay, ScoreDisplay* pSecondaryScoreDisplay, Inventory* pInventory, ScoreKeeper* pPrimaryScoreKeeper, ScoreKeeper* pSecondaryScoreKeeper );

protected:
	NoteField		m_NoteField;

};

#endif

/*
 * (c) 2001-2004 Chris Danford
 * All rights reserved.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, and/or sell copies of the Software, and to permit persons to
 * whom the Software is furnished to do so, provided that the above
 * copyright notice(s) and this permission notice appear in all copies of
 * the Software and that both the above copyright notice(s) and this
 * permission notice appear in supporting documentation.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
 * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
 * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
 * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 */
