/*
 * pawstexturemanager.h - Author: Andrew Craig
 *
 * Copyright (C) 2003 Atomic Blue (info@planeshift.it, http://www.atomicblue.org)
 *
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation (version 2 of the License)
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 */
// pawstexturemanager.h: interface for the pawsTextureManager class.
//
//////////////////////////////////////////////////////////////////////

#ifndef PAWS_TEXTURE_MANAGER
#define PAWS_TEXTURE_MANAGER

#include <csutil/ref.h>
#include <csutil/csstring.h>
#include <csutil/objreg.h>
#include <csutil/parray.h>
#include <cstool/cspixmap.h>
#include <igraphic/image.h>
#include <csgeom/csrectrg.h>

#include <ivideo/texture.h>
#include <iutil/vfs.h>
#include <iutil/document.h>

class pawsTextureManager;

/** A description of an image.
 * The image description consists of the basic things that make up an
 * image.  It also tracks the resource name for this description so you
 * can easily find it.  
 */
class psImageDescription
{
public:
    psImageDescription( pawsTextureManager  *manager );

    /** Create the texture for this description.
     * When these are read in from the xml file the textures are not
     * created.  This will populate the texture handle using the internal
     * data.
     */
    bool CreateTexture( iObjectRegistry* objectReg );
    
    /** This is a shared resource so requires it to be decref'd.
     * This special decref will see if this is a 'stay-in-memory' type image.
     * If so then it is not deleted even though there may be 0 references to it.
     * This would be something like mouse pointers or screen backgrounds. 
     * Basically things that are commonly used but may only have one active at 
     * a time.  Things that will not be stay-in-memory maybe things like the
     * splash screen and character creation screens.
     */
    void DecRef();

public:

    pawsTextureManager* texManager;

    /// The VFS path to the file.
    csString imageFileLocation;

    /// The resource name ( or identifier ) for this description.
    csString resourceName;

    /// If not all of the image is to be used then this holds the part to use.
    csRect   textureRectangle;
    
    int width;
    int height;

    /// The default alpha value that should be used. 
    int      defaultAlphaValue;

    /// The default transparent colour.
    int      defaultTransparentColourRed;
    int      defaultTransparentColourGreen;
    int      defaultTransparentColourBlue;

    bool     preLoad;
    bool     tiled;

    /// Track if we should really remove this after we loose the last ref to it.
    bool     stayInMemory;

    /// The actual texture handle.
    csRef<iTextureHandle> texture;
    
    /// The total objects ref'ing this description.
    int refCount;

    /**
     * The actual image.
     * Some code (e.g. the OS mouse code) doesn't need a texture handle
     * but an iImage instead, so some room for storage is provided here.
     */
    csRef<iImage> image;
};



/** Main texture manager that is used to share resources.
 */
class pawsTextureManager  
{
public:
    pawsTextureManager( iObjectRegistry* objectReg );
    virtual ~pawsTextureManager();

    /** Loads an image list from xml. 
     * The format for an image is:
     * <pre>
     * <image file="/this/path/to/image.png" resource="commonName">
            <texturerect x="0" y="0" width="32" height="32" />
            <alpha level="128" />   
            <trans r="255" g="0" b="255" />
            <state preload="yes" remaininmemory="yes" />
     * </image>
     *
     * @param listName The VFS path to the list file.
     * 
     * @return true if the list was loaded properly.
     */ 
    bool LoadImageList( const char* listName );

    /** Get a description of an image.
     * This tries to find a description of the resource name and will return 
     * that description. It can then be used to create a pawsImage. Not that 
     * this function does an incref on the image description so you should call
     * DecRef() when you are done with it.
     *
     * @param name The resource name to look for. 
     * 
     * @return The description or NULL if not found.
     */
    psImageDescription* GetImageDescription( const char* name );

    /** Remove a description from the list.
     * This removes an image from the list once we are totally finished with it.
     * ie there will not be any more refs to it.
     *
     * @param name The description to remove from the list.
     */
    void Remove( const char* name );
    
    /// Parses the <image></image> data from the xml.
   void ReadImageDescription( iDocumentNode* node );

    /** Used for manually add a description
     * DO NOT DELETE THE DESCRIPTION AFTER THIS!!
     */
    void AddImageDescription( psImageDescription* desc );

protected:
    
    iObjectRegistry* objectReg;

    csRef<iVFS> vfs;
    csRef<iDocumentSystem>  xml; 

    /// List of all the image descriptions.
    csPDelArray<psImageDescription> imageDescriptions;
};


//----------------------------------------------------------------------

/** A basic image for PlaneShift.
*/
class pawsImage : public csSimplePixmap
{
public:
    pawsImage( iObjectRegistry* objectReg );
    
    /** Set the description for this image.
     * This will create an image based on the description passed in.
     * 
     * @param desc A Valid image description to use to build the image.
     */
    void Description( psImageDescription* desc );

    virtual ~pawsImage();

    /** Draw an image at a particular place.
     * Draws with the interal alpha value. 
     *
     * @param x The x screen location.
     * @param y The y screen location.
     */
    void Draw( int x, int y );

    /** Draw an image over a particular frame.
     * This will stretch the image over a given frame.
     * @param frame The rectangle to draw over.
     */
    void Draw( csRect frame );
    
    /** Draw image using a scaled width/height.
     * @param newWidth If set to 0 will use the default width.
     * @param newHeight If set to 0 will use the default height.
     */
    void Draw( int x, int y, int newWidth, int newHeight );

    void SetAlpha ( int alpha ) { alphaValue = alpha; }

    int GetAlpha (void) {return alphaValue;}

    /** Get the description that this image is using to draw.
     * @return a pointer to the psImageDescription or NULL if not found.
     */
    psImageDescription* GetDescription() { return imageDesc; }
    
    int GetWidth()  { return imageDesc->width; }
    int GetHeight() { return imageDesc->height; }
    
protected:
    psImageDescription* imageDesc;

    int alphaValue;
    bool tiled;

    csRef<iGraphics3D> graphics3D;
};

#endif


