TextureEntity* CParaWorldAsset::LoadTexture(const string&  sIdentifier, const string&  fileName, TextureEntity::_SurfaceType nSurfaceType)
{
	string sFileName;
	CParaFile::ToCanonicalFilePath(sFileName, fileName, false);
	CPathReplaceables::GetSingleton().DecodePath(sFileName, sFileName);

	if (fileName[0] == '<')
	{
		//////////////////////////////////////////////////////////////////////////
		// 
		// HTML renderer textures, the file is of the following format <html>[name#]initial page url[;clip size]
		// e.g. "<html>www.paraengine.com"  , "<html>No1#www.paraengine.com". 
		// where key name is "<html>" and "<html>No1", and initial URL is www.paraengine
		//
		//////////////////////////////////////////////////////////////////////////
		if ((fileName[1] == 'h') && (fileName[2] == 't') && (fileName[3] == 'm') && (fileName[4] == 'l') && (fileName[5] == '>'))
		{

			string sInitURL;
			string sKeyName;
			int nPos = (int)sFileName.find_first_of("#./\\:");
			if (nPos > 0 && sFileName[nPos] == '#')
			{
				sInitURL = sFileName.substr(nPos + 1);
				sKeyName = sFileName.substr(0, nPos);
			}
			else
			{
				sInitURL = sFileName.substr(6);
				sKeyName = "<html>";
			}
			pair<TextureEntity*, bool> res = GetTextureManager().CreateEntity(sIdentifier, sKeyName);
			if (res.first != NULL)
			{
				TextureEntity* pNewEntity = res.first;
				// contains the initial url.
				pNewEntity->SetLocalFileName(sInitURL.c_str());
				pNewEntity->SurfaceType = TextureEntity::HTMLTexture;
			}
			return res.first;
		}
		return NULL;
	}

	pair<TextureEntity*, bool> res = GetTextureManager().CreateEntity(sIdentifier, sFileName);
	if (res.second == true)
	{
		TextureEntity* pNewEntity = res.first;
		pNewEntity->SetAsyncLoad(IsAsyncLoading());
		bool bIsRemoteFile = false;
		{
			//////////////////////////////////////////////////////////////////////////
			// 
			// if the file name ends with  _a{0-9}{0-9}{0-9}.dds, it will be regarded as a texture sequence. 
			// and the nSurfaceType will be ignored and forced to TextureSequence 
			//
			//////////////////////////////////////////////////////////////////////////

			int nSize = (int)fileName.size();
			int nTotalTextureSequence = -1;

			if (nSize > 9)
			{
				if (fileName[nSize - 8] == 'a' && fileName[nSize - 9] == '_')
				{
					nTotalTextureSequence = 0;
					for (int i = 0; i < 3; ++i)
					{
						char s = fileName[nSize - 5 - i];
						if (s >= '0' && s <= '9')
						{
							nTotalTextureSequence += (int)(s - '0')*(int)pow((long double)10, i);
						}
						else
						{
							nTotalTextureSequence = -1;
							break;
						}
					}
				}
				// it is a remote file if the filename starts with "http:", or "https:" or "ftp:"
				bIsRemoteFile = ((fileName[0] == 'h' && fileName[1] == 't' && fileName[2] == 't' && fileName[3] == 'p' && (fileName[4] == ':' || fileName[5] == ':')) ||
					(fileName[0] == 'f' && fileName[1] == 't' && fileName[2] == 'p' && fileName[3] == ':'));
			}
			if (!bIsRemoteFile && nTotalTextureSequence > 0)
				nSurfaceType = TextureEntity::TextureSequence;

			//////////////////////////////////////////////////////////////////////////
			// 
			// if the file name ends with  .swf or flv, it will be regarded as a flash texture. 
			// and the nSurfaceType will be ignored and forced to FlashTexture
			//
			//////////////////////////////////////////////////////////////////////////
			if (nSize > 4)
			{
				if ((((fileName[nSize - 3] == 's') && (fileName[nSize - 2] == 'w') && (fileName[nSize - 1] == 'f'))) ||
					((fileName[nSize - 3] == 'f') && (fileName[nSize - 2] == 'l') && (fileName[nSize - 1] == 'v')))
				{
					nSurfaceType = TextureEntity::FlashTexture;
				}
			}
		}

		pNewEntity->SurfaceType = nSurfaceType;
		if (bIsRemoteFile)
		{
			// set as remote file
			pNewEntity->SetState(AssetEntity::ASSET_STATE_REMOTE);
			// remote file only applies to static texture. FlashTexture automatically support remote streaming, and TextureSequence can not be remote. 
			if (nSurfaceType == TextureEntity::StaticTexture)
			{
				// we will delay loading http texture, until it is used for the first time. 
				TextureEntity::TextureInfo* pInfo = (TextureEntity::TextureInfo*) (pNewEntity->GetTextureInfo());
				if (pInfo)
				{
					// TRICKY code LXZ: 2008.3.6: this works around a bug where an HTTP texture is used in a GUI control, where the GUI control can not correctly determine the image size. 
					// by setting negative size, the GUI control will try to retrieve the size of image the next time it is called. 
					pInfo->m_height = -1;
					pInfo->m_width = -1;
				}

				// this new version uses local Resource store. 
				string sCode = "ParaAsset.GetRemoteTexture(\"";
				sCode += sFileName;
				sCode += "\");";
				CGlobals::GetNPLRuntime()->GetMainRuntimeState()->DoString(sCode.c_str(), (int)sCode.size());
			}
			else
			{
				OUTPUT_LOG("warning: http remote texture %s must be static texture type, but we got type=%d \n", fileName.c_str(), nSurfaceType);
			}
		}
	}
	return res.first;
}