/*
 * Licensed under BSD license.  See LICENCE.TXT  
 *
 * Produced by:	Jeff Lait
 *
 *      	Jacob's Matrix Development
 *
 * NAME:        display.h ( Jacob's Matrix, C++ )
 *
 * COMMENTS:
 * 	Draws a view into a map.  Handles timed effects, map memory, etc.
 */

#ifndef __display__
#define __display__

#include "map.h"

#include "event.h"

class SCRPOS;

class DISPLAY
{
public:
    enum YELL_STATE
    {
	YELLSTATE_NONE,
	YELLSTATE_SLASH,
	YELLSTATE_TEXT,		// Contains speach
	YELLSTATE_PAD,		// 1 char padding around speach
    };

    // Rectangle inside of TCOD to display.
    // Border is the memory border added to all sides.
    DISPLAY(int x, int y, int w, int h, int border);
    ~DISPLAY();

    void	 display(POS pos, bool isblind=false);

    // This is in absolute screen coords, ie, bakes in myX and myY
    POS		 lookup(MAP *map, int x, int y) const;

    // Erases our memory.
    void	 clear();

    int		 width() const { return myW; }
    int		 height() const { return myH; }
    int		 bwidth() const { return myW + myBorder*2; }
    int		 bheight() const { return myH + myBorder*2; }
    int		 x() const { return myX; }
    int		 y() const { return myY; }

    void	 postEvent(const EVENT &event)
    { 
	if (!myEventDisable)
	    queue().append(event); 
    }
    int	 	 disableEvents() { return myEventDisable.add(1); }
    int	 	 enableEvents() { return myEventDisable.add(-1); }

    void	 fadeFromWhite();
    // Returns true when complete.
    bool	 fadeToBlack(bool enable);
    bool	 fadeToRed(bool enable);

    // Stores a forget all flag so the memory is wiped the
    // next time we update from main thread.
    void	 pendingForgetAll() { myPendingForgetAll = true; }

    void	 clearLenses() { myShowElevation = myShowSnowDepth = myShowHarvest = false; }
    bool	 showElevation() const { return myShowElevation; }
    void	 setShowElevation(bool show) { myShowElevation = show; }
    void	 toggleShowElevation() { if (!myShowElevation) clearLenses(); myShowElevation = !myShowElevation; }
    bool	 showSnowDepth() const { return myShowSnowDepth; }
    void	 setShowSnowDepth(bool show) { myShowSnowDepth = show; }
    void	 toggleShowSnowDepth() { if (!myShowSnowDepth) clearLenses(); myShowSnowDepth = !myShowSnowDepth; }
    bool	 showHarvest() const { return myShowHarvest; }
    void	 setShowHarvest(bool show) { myShowHarvest = show; }
    void	 toggleShowHarvest() { if (!myShowHarvest) clearLenses(); myShowHarvest = !myShowHarvest; }

    bool	 showAvatarDensity() const { return myShowAvatarDensity; }
    bool	 showMobDensity() const { return myShowMobDensity; }
    bool	 showMobGivenDensity() const { return myShowMobGivenDensity; }
    void	 setShowAvatarDensity(bool show) { myShowAvatarDensity = show; }
    void	 setShowMobDensity(bool show) { myShowMobDensity = show; if (show) myShowMobGivenDensity = false; }
    void	 setShowMobGivenDensity(bool show) { myShowMobGivenDensity = show; if (show) myShowMobDensity = false; }
    void	 toggleShowAvatarDensity() { myShowAvatarDensity = !myShowAvatarDensity; }
    void	 toggleShowMobDensity() { myShowMobDensity = !myShowMobDensity; if (myShowMobDensity) myShowMobGivenDensity = false; }
    void	 toggleShowMobGivenDensity() { myShowMobGivenDensity = !myShowMobGivenDensity; if (myShowMobGivenDensity) myShowMobDensity = false; }

    void	 setGivenPos(POS pos) { myGiven = pos; }
    POS		 givenPos() const { return myGiven; }


private:
    EVENT_QUEUE	 &queue() { return myEQ; }

    // Render to gfx engine layer.  the x/y are relative to this display.
    void	 printChar(int displayx, int displayy, u8 symbol, ATTR_NAMES attr) const;
    void	 printChar(int displayx, int displayy, u8 symbol) const;
    void	 printAttrFore(int displayx, int displayy, ATTR_NAMES attr) const;
    void	 printAttrFore(int displayx, int displayy, u8 r, u8 g, u8 b) const;
    void	 printAttrBack(int displayx, int displayy, ATTR_NAMES attr) const;
    void	 printAttrBack(int displayx, int displayy, u8 r, u8 g, u8 b) const;

    void	 scrollMemory(int dx, int dy);
    void	 rotateMemory(int angle);
    u8		 recall(int x, int y) const;
    POS		 recallPos(int x, int y) const;
    void	 note(int x, int y, u8 val, POS pos);

    void	 setYellFlag(int x, int y, YELL_STATE state);
    YELL_STATE	 yellFlag(int x, int y) const;

    void	 drawYellMessage(int px, int py, int dx, int dy,
				const char *text,
				ATTR_NAMES attr);

    bool	 checkRoomForText(int px, int py, int textlen);
    void	 findTextSpace(int &px, int &py, int dy, int textlen);

    u8		*myMemory;
    POS		*myMemoryPos;
    u8		*myYellFlags;
    int		 myX, myY;
    int		 myW, myH;
    int		 myBorder;
    int		 myMapId;
    SCRPOS_PTR	 myPosCache;
    int		 myVerseId;
    TEXTUREF	 myMobDensityCache;

    POS		 myGiven;

    bool	 myShowElevation;
    bool	 myShowSnowDepth;
    bool	 myShowHarvest;

    bool	 myShowAvatarDensity;
    bool	 myShowMobDensity;
    bool	 myShowMobGivenDensity;

    int		 myWhiteFadeTS;
    bool	 myFadeFromWhite;

    int		 myBlackFadeTS;
    bool	 myFadeToBlack;

    int		 myRedFadeTS;
    bool	 myFadeToRed;

    // Where we track all of our active events.
    EVENTLIST	 myEvents;

    // Where incoming events go
    EVENT_QUEUE	 myEQ;

    volatile bool	 myPendingForgetAll;

    ATOMIC_INT32		myEventDisable;
};

#endif
