#pragma once

#include "core/core.h"
#include "bitsearch.h"

enum BitMoveGenType
{
    mgtFull			=	0,			// all legal moves (actually never used)
    mgtEvasions		=	1,			// check evasions
	mgtQEvasions	=	2,			// qsearch check evasions (no singlereply => faster)
    mgtCaptures		=	3,			// captures + all promotions
    mgtQCaptures	=	4,			// captures + queen promotions
    mgtQCapturesWithChecks	=	5,	// qcaps + qchecks
    mgtQChecks		=	6,			// checking moves
    mgtNormal		=	7,			// quiter moves
    mgtBadCaptures	=	8,			// bad captures (continuing)
    mgtFinished		=	9,			// specal flag: movegen_finished
};

class BitMoveGen
{
protected:
    const BitSearch &search;			// search ref
    const BitSearchStackEntry *stack;	// search stack refptr
    i32 ply;							// search stack current ply
    const BitBoard &board;				// board ref
    const BitMove &hashmv;				// hashmv ref

    BitMoveGenType phase;				// current type/phase
    i32 moveCount;						// generated moves count
    BitMove moves[ bmaxMoves ];			// generated moves list
    i32 mval[ bmaxMoves ];				// generated move values
    i32 badCapCount;					// generated bad captures count
    BitMove badCaps[ 64 ];				// generated bad captures list
//	i32 badmval[ 64 ];					// generated bad caps values
    i32 finishedCount;					// special (already finished) move count
    BitMove finishedMoves[ 5 ];			// special (already finished) moves
    i32 returnCount;					// simply a value returned by count()
    i32 id;								// current move id. points to moves or badCaps depending on phase
    i32 specPhase;						// special move phase. 0 = pv, 1 = hash, 2 = matekiller, 3+ = killer1+
    i32 generated;						// number of moves generated (helps to avoid searching for best score in some cases)

    // new: pseudo-legal move generators:
    i32 genCaps( BitMove *m, bool underpromo = 1 );
    i32 genQChecks( BitMove *m );
    i32 genQuiet( BitMove *m );
    // evasions: always legal!
    i32 genEvasions( BitMove *m );

    // score capturing moves
    // full: 1 = full, 0 = in qsearch
    void scoreCaps( i32 count, BitMove *m, i32 *mval, BitMove *badm, i32 &badcnt, bool full = 1 );
    // score quiescence capturing moves
    void scoreQCaps( i32 count, BitMove *m, i32 *mval );
    // score normal moves
    void scoreQuiet( i32 count, BitMove *m, i32 *mval );
    // score QChecks
    void scoreQChecks( i32 count, BitMove *m, i32 *mval );
    // score evasions
    void scoreEvasions( i32 count, BitMove *m, i32 *mval );

public:
    u64 discovered;						// discovered check candidates
    u64 pins;							// NEW: pins (only valid if type != mgtEvasions)
    BitMoveGen( const BitBoard &b, i32 ply_,
                const BitSearch &search_, const BitMove &hashmv_, BitMoveGenType type = mgtFull );

    // return number of moves (only valid when generating full/evasions, in all other cases returns 3)
    i32 count() const;

    // returns next move (in mv_ref)
    // returns true if valid, otherwise no more moves available
    bool next( BitMove &mv );
};

// synchronized version
class BitMoveGenSync : public BitMoveGen
{
protected:
	mutable Mutex mutex;
public:
    // return number of moves (only valid when generating full/evasions, in all other cases returns 3)
    i32 count() const;

    // returns next move (in mv_ref)
    // returns true if valid, otherwise no more moves available
    bool next( BitMove &mv );
};
