#include "texture.h"
//#include "globalvar.h"

#include <GL/glew.h>
#include <GL/glu.h>

#include <wx/image.h>
#include <wx/zipstrm.h>
#include <wx/archive.h>
#include <wx/fs_zip.h>
#include <wx/wfstream.h>
#include <wx/mstream.h>
#include <wx/glcanvas.h>
#include <stdio.h>

//#include "tools/debug.h"

//загрузить текстуру из потока
unsigned int glLoadBitmap0(int mip,wxInputStream &mis,wxString ext)
{
	if(mis.IsSeekable()) mis.SeekI(0,wxFromStart);
	unsigned int texName=0;
	glEnable(GL_TEXTURE_2D);
	//glPixelStorei(GL_UNPACK_ALIGNMENT,1);
	glGenTextures(1,&texName);
	glBindTexture(GL_TEXTURE_2D,texName);

//	glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE, GL_REPLACE);
	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);  //Texture blends with object background
//	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);  //Texture does NOT blend with object background

//Select a filtering type. BiLinear filtering produces very good results with little performance impact
//    GL_NEAREST               - Basic texture (grainy looking texture)
//    GL_LINEAR                - BiLinear filtering
//    GL_LINEAR_MIPMAP_NEAREST - Basic mipmapped texture
//    GL_LINEAR_MIPMAP_LINEAR  - BiLinear Mipmapped texture
	//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_LINEAR);//GL_NEAREST GL_LINEAR
	//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_LINEAR);
	//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, GL_LINEAR);
	//int mip=2;
	if(mip==0)
	{
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // only first two can be used
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // all of the above can be used
	}else
	if(mip==1)
	{
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // only first two can be used
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // all of the above can be used
	} else
	if(mip==2)
	{
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST); // only first two can be used
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); // all of the above can be used
	} else
	if(mip==3)
	{
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR); // only first two can be used
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // all of the above can be used
	}

	//unsigned short Format=GL_RGB;
	wxImage *m_Image;
	if(ext.Lower()==_T("jpg"))
		m_Image = new wxImage( mis, wxBITMAP_TYPE_JPEG, -1 );
	else
	if(ext.Lower()==_T("bmp"))
		m_Image = new wxImage( mis ,wxBITMAP_TYPE_BMP, -1 );
	else
	if(ext.Lower()==_T("tga"))
	{
		m_Image = new wxImage( mis ,wxBITMAP_TYPE_TGA, -1 );
	}else
	if(ext.Lower()==_T("png"))
	{
		m_Image = new wxImage( mis ,wxBITMAP_TYPE_PNG, -1 );
	}else return 0;
	if(!m_Image->IsOk()) //если плохой рисунок выходим
	{
		delete m_Image;
		return 0;
	}

	wxImage glImage = m_Image->Mirror(false); //because GL reads textures with 0,0 being the lower-left, we have to flip each image vertically
	if(glImage.HasMask()) glImage.InitAlpha();


	//изза того что в wxImage альфа канал храниться отделтно перебираем данные текстуры
	//free(data);
	unsigned char* data = (unsigned char*)malloc(glImage.GetWidth() * glImage.GetHeight() * 4);
	unsigned int d = 0;
	for (int y = 0; y < glImage.GetHeight(); y++)
	{
		for (int x = 0; x < glImage.GetWidth(); x++)
		{
			data[d++] = glImage.GetRed(x, y);
			data[d++] = glImage.GetGreen(x, y);
			data[d++] = glImage.GetBlue(x, y);

			if(glImage.HasAlpha())
			{
				unsigned char a=glImage.GetAlpha(x, y);
				data[d++] = a;
			}
			else
				data[d++] = 255;
		}
	}

	if((mip==0)||(mip==1))
		glTexImage2D(GL_TEXTURE_2D, 0, 4, glImage.GetWidth(), glImage.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
	else
		gluBuild2DMipmaps(GL_TEXTURE_2D, 4, glImage.GetWidth(), glImage.GetHeight(), GL_RGBA, GL_UNSIGNED_BYTE, data);

	free(data);

	delete m_Image;
	return texName; // Returns the current texture OpenGL ID
}
//------------------------------------------------------------------------------
//загрузить текстуру из файла
unsigned int glLoadBitmap(int mip,wxString filename)
{
	if(!wxFile::Exists(filename)) return 0;
	wxFileInputStream mis(filename);
	return glLoadBitmap0(mip,mis,filename.AfterLast(_T('.')));
}
//------------------------------------------------------------------------------
/*TMaterial::TMaterial(TEmptySetPoints *parent):TEmptyPoint(parent)
{
	textureid=0;
	ColorAmbientRGB.r=0.2f; // 0.2 по умолчанию в OpenGL
	ColorAmbientRGB.g=0.2f;
	ColorAmbientRGB.b=0.2f;
	ColorAmbientRGB.a=1.0f;
	ColorDiffuseRGB.r=0.8f; // 0.8 по умолчанию в OpenGL
	ColorDiffuseRGB.g=0.8f;
	ColorDiffuseRGB.b=0.8f;
	ColorDiffuseRGB.a=1.0f;
	ColorSpecularRGB.r=0.0f; // 0.0 по умолчанию в OpenGL
	ColorSpecularRGB.g=0.0f;
	ColorSpecularRGB.b=0.0f;
	ColorSpecularRGB.a=1.0f;
	data=NULL;
}
//------------------------------------------------------------------------------
TMaterial::~TMaterial()
{
	if(data!=NULL) free(data);
}
//------------------------------------------------------------------------------
//загрузить рисунок из буфера
void TMaterial::LoadImage()
{
	if(imgpath!=_T(""))
	{
		wxMemoryInputStream mis(data,size);

		textureid=glLoadBitmap0(2,mis,imgpath.AfterLast('.'));

		free(data);
		data=NULL;
	}
}
//------------------------------------------------------------------------------
void TMaterial::LoadS(wxInputStream *is)
{
	is->Read(&date,4); //read date
	is->Read(&del,1); //read del
	is->Read(&ObjectID,4); //read ObjectID
	if(!del)
	{
		is->Read(&ColorDiffuseRGB.r,4);
		is->Read(&ColorDiffuseRGB.g,4);
		is->Read(&ColorDiffuseRGB.b,4);
		is->Read(&ColorDiffuseRGB.a,4);

		is->Read(&Lighting,1);
		is->Read(&blend,1);
		name=loadUTF8String(is); //загрузим название материала
		imgpath=loadUTF8String(is); //загрузим название текстуры
		//загрузим данные текстуры bmp,jpg,tif,png
		is->Read(&size,4);
		if(size>0)
		{
			data = (unsigned char*)malloc(size); //временно в поток потому что текстуру загружать в потоке отличном от контекста нельзя
			is->Read(data,size);
			LoadImage(); //загрузить текстуру и освободить память
		}
	}
}
//------------------------------------------------------------------------------
//устанавливаем материал перед вызовом обьекта
void TMaterial::Release()
{
	//прозрачность
	if(blend)
	{
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		glEnable(GL_BLEND);
	} else glDisable(GL_BLEND);
	if(Lighting) //со светом
	{
		glEnable(GL_LIGHTING);
		glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&ColorAmbientRGB);
		glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&ColorDiffuseRGB);
		glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*)&ColorSpecularRGB);
	}else
	{//без света
		glDisable(GL_LIGHTING);
		glEnable(GL_COLOR_MATERIAL);
		glColor4f(ColorDiffuseRGB.r,ColorDiffuseRGB.g,ColorDiffuseRGB.b,ColorDiffuseRGB.a);
		glDisable(GL_COLOR_MATERIAL);
	}
	//если текстурированна
	if(textureid!=0)
	{
		glBindTexture(GL_TEXTURE_2D, textureid);
		glEnable(GL_TEXTURE_2D);
		//чтобы цвет не воздействовал на текстуру если она есть
		glEnable(GL_COLOR_MATERIAL);
		glColor4f(1,1,1,ColorDiffuseRGB.a);
		glDisable(GL_COLOR_MATERIAL);
	} else glDisable(GL_TEXTURE_2D);
}
//------------------------------------------------------------------------------
TMaterials::TMaterials(TCity *parent) :TEmptySetPoints(parent)
{
	ext=_T("mat");
	fid=11347;
}
//------------------------------------------------------------------------------
TMaterials::~TMaterials()
{
}
//------------------------------------------------------------------------------
void TMaterials::LoadS(wxInputStream *is)
{
	if(is==NULL) return;
	unsigned int i,count;
	is->Read(&i,4);	if(i!=fid) return; //проверка на id файла
	is->Read(&version,4); //версия файла
	is->Read(&fMaxObjectID,4); //максимальный id для этого файла
	is->Read(&fdatesrv,4); //время последнего обновления с сервера сек с 2000
	is->Read(&count,4); //кол во дорог
	List = new TEmptyPoint*[count];
	for(i=0;i<count;i++)
	{
		TMaterial *Material = new TMaterial(this);
		Material->LoadS(is);
		List[i]=Material;
		m_count++;
	}
}
//------------------------------------------------------------------------------
void TMaterials::MouseLUp(RfPointXYZ fGLMLUpXYZ)
{
}
//------------------------------------------------------------------------------
void TMaterials::MouseRUp(RfPointXYZ fGLMLUpXYZ)
{
}
//------------------------------------------------------------------------------
void TMaterials::MouseMove(RfPointXYZ fGLMLUpXYZ)
{
}
//------------------------------------------------------------------------------
void TMaterials::OnMouseWhell(float f)
{
}
//------------------------------------------------------------------------------
void TMaterials::LoadComplete()
{
}*/
//------------------------------------------------------------------------------
