/* Player - Accepts input, knocks down TapNotes that were stepped on, and keeps score for the player. */

#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

// The higher this is, the more checkpoints we'll establish in advance
#define PIU_HOLD_CHECK_ADVANCE	100

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 CrossedPIUHoldHeadRow( 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();

	// These exist to make the Update() function tidier
	void UpdateHoldNotes( float fDeltaTime, int iSongRow );
	void UpdateRollNotes( float fDeltaTime, int iSongRow );

	void UpdatePIUHoldNotes( float fDeltaTime, int iSongRow );
	void UpdatePIUHoldScoring();

	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_iPIUHoldHeadRowLastCrossed;

	// Hold checkpoints
	int CheckDistanceBetweenCheckpoints( int iRow );
	bool StartOfNewTickSegment( int iRow, int iTickSegment );
	int StartOfTickSegment( int iTickSegment );
	int StartOfTickSegmentZero();
	int CurrentSegmentForPreloading( int iRow );
	void SetInitialCheckpoints( int iStartRow );
	void UpdateCheckpoints();
	bool TapNoteOnCheckpoint( int iTrack, int iRow );

	int				m_iCurrentTickSegment;

	//int			m_iNumNotesThisCheckpoint;
	int				m_iNumHoldsThisCheckpoint;

	//int			m_iNumNotesNextCheckpoint[PIU_HOLD_CHECK_ADVANCE];
	int				m_iNumHoldsNextCheckpoint[PIU_HOLD_CHECK_ADVANCE];
	int				m_iNextCheckpointRow[PIU_HOLD_CHECK_ADVANCE];

	//int			m_iNumHitNotesForCheckpoint;
	int				m_iNumHitHoldsForCheckpoint;

	bool			m_bInitialCheckpointSet;
	bool			m_bPrepareNextCheckpoint;
	bool			m_bNeedCheckpoint;
	bool			m_bCheckpointAlreadyChecked;	// Because we may check a song row more than once over multiple updates

	// 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.
 */
