#pragma once

#include "bitboard.h"

// pawn hash structure
typedef struct BitPawnHash
{
    u64 hash;				// pawn hash
    u64 passed;				// passed pawn mask
    i32 score[2];			// pure_pawn score: 0 = opening, 1 = endgame (from white's pov)
    i32 reserved[2];		// reserved for future use
    // TODO :more?
} BitPawnHash;

class BitKPK;				// new: KPK table!

class BitEval
{
protected:
    i32 evalCacheSize;		// eval cache size in entries
    i32 pawnHashSize;		// pawn hash size in entries
    BitPawnHash *pawnHash;	// pawn hash itself
    u64 *evalHash;			// eval cache hashes
    i16 *evalScore;			// eval cache hashed score
    i32 debugFlag;			// debug flag

    BitPawnHash tphash;		// dummy value

    i32 realDist( i8 turn, u8 kp, u8 pp, const u64 &blocked );
public:
    i32 skill;				// new: skill value. 100 = maximum skill, 0 = totally lame
    i32 safetyEval[2];
    typedef i16 *bitBonusTable[ 2 ][ 2 ][ 7 ];

    const BitBoard *board;	// board
    i32 score[2];			// final score (0 = opening/midgame score, 1 = endgame score)
    i32 material[2];		// pure material for each side
    i32 turn;				// turn
    i32 check;				// check flag
    u64 kingMask[2];		// king position mask
    u64 all;				// all piece mask (including kings)

    i32 tmat[2];			// total non-pawn material [who]

    i32 attackerCount[2];	// king safety attacker count [who] (i.e. number of pieces which attack me)
    i32 attackerScale[2];	// king safety attacker scale [who] (each piece type adds different scale (or weight))
    u64 safetyMask[2];		// king safety important squares [who]
    u64 attackMask[2][7];	// attack masks: [who][piece_type]
    u64 allAttackMask[2];	// simply ored attack masks!
    u64 passedPawnMask[2];	// passed pawn masks [who]
    u64 knightOrBetter[2];	// knight or more valuable piece masks [who] (not including kings!)
    u64 rookOrBetter[2];	// rook or more valuable piece masks [who] (not including kings!)
    i32 cantIntercept[2];	// can't intercept passed pawns (best = min distance) [who]
    u8 loneKing[2];			// lone king flags [who]
    u8 levBuilt[2];			// dist_levels_built?
    u64 levels[2][10];		// distance levels [turn][level]	(enemy_king -> passed pawns)

    BitPawnHash *pawns;		// pawn hash entry ptr (should be always valid, no matter if pawnHash table is used!)

    bitBonusTable *bonusTable;	// position bonus table (to allow dynamic adjustments) (sometimes called piece-square tables)

    BitKPK *kpkEval;		// eval kpk/kkp

    // default: 2MB evaluation cache!
    BitEval( i32 evalCacheSizeBytes = 2*1048576 );
    virtual ~BitEval();

    // evaluate position!
    virtual i32 eval( const BitBoard &b, i32 alpha = -bmate, i32 beta = +bmate );

    // custom evaluation after everyhting else has been done!
    // should modify score[0] and score[1]
    virtual void customEval();

    // clear eval cache(s)
    virtual void clearCache();

    // set debug flag
    virtual i32 setDebugFlag( i32 df = 0 );

    // evaluators for individual pieces
    virtual void whiteKnight( u8 pos );
    virtual void blackKnight( u8 pos );
    virtual void whiteBishop( u8 pos );
    virtual void blackBishop( u8 pos );
    virtual void whiteRook( u8 pos );
    virtual void blackRook( u8 pos );
    virtual void whiteQueen( u8 pos );
    virtual void blackQueen( u8 pos );
    virtual void whiteKing( u8 pos );
    virtual void blackKing( u8 pos );

    // new: to support pawn hashing!
    void whitePawnHashed( u8 pos );
    void blackPawnHashed( u8 pos );
    void whitePassedPawn( u8 pos );
    void blackPassedPawn( u8 pos );
};
