/*
 * $Id: image.h 4270 2016-11-06 11:02:47Z antonin.misek-skoda-auto.cz $
 *
 * Description  : One line description of file.
 * Author       : Vaclav Kyba <mail/Jabber: vaseo1@gmail.com>  <ICQ: 98576293>
 * 
 * Purpose      :
 *     Long description of what the file is for.
 */


#ifndef __IMAGE_H__
#define __IMAGE_H__

#include <stdlib.h>
#ifndef VRUT_HPC
#include <GL/glew.h>
#else
#include "OGLconstants.h"
#endif
#include <wx/filename.h>
#include <wx/image.h>

#include "countable.h"
#include "VrutApi.h"

namespace VRUT
{
	///Baseclass for image container - abstract
	class VRUT_CORE_API Image : public Countable
	{
	protected:
		///Path to file with image data
		wxFileName filename;
		wxFileName filenames[6];

	public:
		///Sampler type
		enum TEXTURE_SAMPLER_TYPE
		{
			TEX2D,
			TEXCUBE,
			TEXTURE3D
		};

		///Image type
		enum IMAGE_TYPE
		{
			UNKNOWN,
			WXIMAGE,
			DDSIMAGE,
			HDRIMAGE,
		};

		enum ALPHA_USAGE_TYPE
		{
			MASK,
			TRANSPARENCY
		};

	private:
		///Image type
		IMAGE_TYPE imageType;
	protected:
		///Is the alpha channel used for masking (only values 0 or 255) or transparency (all kinds of values)
		ALPHA_USAGE_TYPE alphaUsageType;
		///Helper variable. Determination is expensive.
		bool transparency;
		///We need to know whether the image is a simple image or a cube image
		bool cube;

	public:
		///Class constructor
		Image(IMAGE_TYPE _imageType = UNKNOWN, bool cube = false) : imageType(_imageType), alphaUsageType(TRANSPARENCY), transparency(false), cube(cube) {}
		///Class destructor
		virtual ~Image()  {}
		
		///Is image properly loaded?
		virtual bool IsOk() const = 0;
		///Is it a cube texture
		bool IsCube() const { return cube; }
		///Get filename
		const wxFileName * GetFilename() const
		{
			return &filename;
		}

		static const int FLIP_HORIZONTALLY = 0x1;
		static const int FLIP_VERTICALLY = 0x2;
		///Load image data from file
		/// \param flip .. bitwise or between FLIP_HORIZONTALLY and FLIP_VERTICALLY defining whether to flip loaded image
		virtual bool Load(const wxString & fname, int cubeSide=-1, int flip = 0)
		{
			if (wxFileName::FileExists(fname))
			{
				if (cubeSide<=0)
				{
					filename.Assign(fname);
					filenames[0].Assign(fname);
				}
				else if (cubeSide<6)
					filenames[cubeSide].Assign(fname);
				return true;
			}
			return false;
		}
		///Get image type
		const IMAGE_TYPE GetType() const
		{
			return imageType;
		}

		bool IsTransparent() const { return transparency; }

		///Get alpha usage type
		ALPHA_USAGE_TYPE GetAlphaUsageType() const
		{
			return alphaUsageType;
		}
#ifndef VRUT_HPC
		///Updates tex_object texture from image in CURRENT OpenGL context. tex_object must have been created (by simple glGenTextures for example)
		/// \param tex_object OpenGL texture object which should contain new texture
		/// \param buildAsType Type of texture to be created
		/// \param create_mipmaps true if mipmaps should be also created
		virtual void UpdateOglTexture(GLuint tex_object, const TEXTURE_SAMPLER_TYPE buildAsType, bool create_mipmaps) const = 0;

		///Checks if the texture does not exceed maximum dimensions permitted by the OGL driver. If it does, it scales the texture down.
		static bool CheckAndFixImageResolution(wxImage *image, TEXTURE_SAMPLER_TYPE type);
#endif
		///Get \c true if image has alpha channel and determine the alpha usage
		virtual bool SetTransparencyAndSetAlphaUsage(bool testPixels=true) = 0;
		///Get the width of the image
		virtual int GetWidth() const = 0;
		///Get the height of the image
		virtual int GetHeight() const = 0;
		///Save the image to file
		virtual bool Save(wxString filename) const = 0;

		///Get name of given cube side
		const wxString GetCubeSideName(int cubeSide) const
		{
			if ((cubeSide<=0) || (cubeSide>6))
				return filename.GetFullPath(wxPATH_NATIVE);
			return filenames[cubeSide].GetFullPath(wxPATH_NATIVE);
		}
	};
}

#endif
