// ---------------------------------------------------------------------------
// 
//   Lily Engine alpha
// 
//   Copyright (c) 2010 Clifford Jolly
//     http://cliffjolly.com
//     cliff@cliffjolly.com
// 
// ---------------------------------------------------------------------------
// 
//   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; either version 2 of the License, or
//   (at your option) any later version.
//  
//   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
// -------------------------- END HEADER -------------------------------------

#pragma once

#include <string>
#include <vector>
#include <map>

#include "../math/vector2d.h"

class Texture;

struct TextureInfo {
	bool filter;
};

namespace Threads {
    class Thread;
    class Mutex;
};

/** @brief Resource manager for Textures. */
class TextureManager {

    public:

        /// Constructor.
        TextureManager(void);
		
        /// Destructor.
        virtual ~TextureManager(void);
		
        /** @brief Get a Texture by its file name.
         * @note Don't use this. It's not implemented. (FIXME)
         * @param texName The texture file name.
         * @return A pointer to the texture.
         * */
        Texture *getTextureByName(const std::string &texName);
		
        /** @brief Get a Texture by its index number.
         * @param index The index number.
         * @return The Texture.
         * */
        Texture *getTextureByIndex(int index);
		
        /** @brief Get a Texture's index number by its name.
         * @param texName The name of the Texture.
         * @return The Texture's index.
         * */
        int getTextureIndexByName(const std::string &texName);
		
        /** @brief Get a Texture's name by its index number.
         * @param index The Texture's index number.
         * @return The name of the texture.
         * */
        std::string getTextureNameByIndex(int index);
		
        /** @brief Start loading a Texture in the background.
         * @note Not implemented yet. (FIXME)
         * */
        void backgroundLoad(const std::string &texName);
		
        /** @brief Free old, unused Textures to get some memory back.
         * @param maxAge Textures that haven't been used since this
         *   many frames ago will be purged.
         * */
        void cleanOldTextures(unsigned int maxAge = 9000);
	
        void clearAllTextures(void);
	
        static TextureManager *get(void);
		
        /// Set linear texel interpolation instead of nearest-neighbor
        /// for a given texture. Defaults to true.
        void setTextureFilter(int index, bool filter);
		
        /// Get linear texel interpolation setting for a texture.
        bool getTextureFilter(int index);
		
        /// Turn shaders on or off.
        void setShadersEnabled(bool enable);
		
        /// Get shaders flag.
        bool getShadersEnabled(void);
		
        /// Get whether or not GLEW thinks we can use shaders.
        bool getShadersDetected(void);

        void scanTextureSizes(const std::string &path);

        Vector2D getTextureSize(const std::string &path);
		
    private:

        Texture *createTexture(const std::string &fileName);
        std::map<std::string, int> textureIndicesByName;
        std::vector<std::string> textureNames;
        std::vector<Texture*> textures;
        std::vector<TextureInfo *> textureInfos;
        bool shadersEnabled;

        // Texture load thread stuff.
        Threads::Thread *loadWorkerThread;
        bool loadWorkerQuit; // Set this to tell the load worker it's
                             // time to shutdown.
        friend int textureLoadWorkerFunc(TextureManager *manager);
        Threads::Mutex *loadQueueMutex;
        std::vector<Texture*> loadQueue;
        void addTextureToQueue(Texture *tex);

        std::map<std::string, Vector2D> cachedTextureSizes;
};
