/*
* Copyright (c) 2007-2010 Sebastian Brannstrom, Lars Persson, EmbedDev AB
*
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* EmbedDev AB - initial contribution.
*
* Contributors:
*
* Description:
*
*/

#include <e32std.h>
#include <e32base.h>
#include <TXTETEXT.H> // for ELineBreak
#include "PodcastUtils.h"
#include "debug.h"
#include "FeedEngine.h" // for KMaxDescriptionLength
			
EXPORT_C void PodcastUtils::FixProtocolsL(TDes &aUrl)
	{
	HBufC* urlCopy = aUrl.AllocLC();
	TPtr urlCopyPtr (urlCopy->Des());
	urlCopyPtr.LowerCase();
	
	// url is always present so access that								
	// Some pod links are written in format itpc://mylink.net/podcast.xml
	// Symbian HTTP stack does not like itpc:// 
	// Try to use a HTTP instead.
	TInt p = urlCopyPtr.Find(KItpcPrefix);
	if (p >= 0)
		{
		aUrl.Delete(p, KItpcPrefix().Length());
		}

	// Some pod links are written in format pcast://mylink.net/podcast.xml
	// Symbian HTTP stack does not like itpc:// 
	// Try to use a HTTP instead.
	p = urlCopyPtr.Find(KPcastPrefix);
	if (p >= 0)
		{
		aUrl.Delete(p, KPcastPrefix().Length());
		}

	// The URL must start with http://, otherwise the HTTP stack fails.
	TInt pos = urlCopyPtr.Find(KURLPrefix);
	if (pos == KErrNotFound)
		{
		HBufC* newUrl = HBufC::NewL(aUrl.Length() + KURLPrefix().Length());
		TPtr ptr = newUrl->Des();
		ptr.Append(KURLPrefix());
		ptr.Append(aUrl);

		// replace the url buffer
		aUrl.Copy(*newUrl);
		delete newUrl;					
		}
	
	CleanupStack::PopAndDestroy(urlCopy);
	}


EXPORT_C void PodcastUtils::CleanHtmlL(TDes &str)
{
	DP("PodcastUtils::CleanHtmlL BEGIN");
	if (str.Length() == 0)
		{
		return;
		}
// miscellaneous cleanup
	DP("    miscellaneous cleanup");
	const TChar KLineBreak(CEditableText::ELineBreak); 
	_LIT(KNewLine, "\n");
	_LIT(KNewLineWindows, "\r\n");
	ReplaceString(str, KNewLine, KNullDesC);
	ReplaceString(str, KNewLineWindows, KNullDesC);

// strip out HTML tags
	DP("    strip out HTML tags");
	TInt startPos = str.Locate('<');
	TInt endPos = str.Locate('>');
	HBufC* tmpBuf = HBufC::NewLC(KMaxDescriptionLength);
	TPtr tmp(tmpBuf->Des());
	while (startPos != KErrNotFound && endPos != KErrNotFound && endPos > startPos) {
		//DP1("Cleaning out %S", &str.Mid(startPos, endPos-startPos+1));
		tmp.Copy(str.Left(startPos));
		TPtrC ptr=str.Mid(startPos, endPos-startPos+1);
		_LIT(KHtmlBr, "<br>");
		_LIT(KHtmlBr2, "<br />");
		_LIT(KHtmlBr3, "<br/>");
		_LIT(KHtmlP, "<p>");
		if (ptr.CompareF(KHtmlBr)== 0 || ptr.CompareF(KHtmlBr2)== 0 || ptr.CompareF(KHtmlBr3)== 0)
			{
			tmp.Append(KLineBreak);
			}
		else if (ptr.CompareF(KHtmlP) == 0)
			{
			tmp.Append(KLineBreak);
			tmp.Append(KLineBreak);
			}
		
		if (str.Length() > endPos+1) {
			tmp.Append(str.Mid(endPos+1));
		}
		
		str.Copy(tmp);
		startPos = str.Locate('<');
		endPos = str.Locate('>');
	}
		
// change HTML encoded chars to unicode
	DP("    change HTML encoded chars to unicode");
	startPos = str.Locate('&');
	endPos = str.Locate(';');
	while (startPos != KErrNotFound && endPos != KErrNotFound && endPos > startPos && endPos < str.Length())
		{
//		DP2("startPos=%d, endPos=%d", startPos, endPos);
		TPtrC ptr(str.Mid(startPos+1, endPos-startPos));
		// check for whitespace
		if (ptr.Locate(' ') == KErrNotFound)
			{
			// numerical constant
			if (ptr[0] == '#')
				{ 
				TUint length = endPos - startPos;
				if (length > 2)
					{
					tmp.Copy(str.Left(startPos));
					ptr.Set(str.Mid(startPos+2, length-2));
					
					TUint charCode = 0;
				
					if (ptr[0] == 'x')
						{
						// hexadecimal
						ptr.Set(ptr.Mid(1));
						TLex16 lex(ptr);
						lex.Val(charCode, EHex);	
						}
					else
						{
						//decimal
						TLex16 lex(ptr);
						lex.Val(charCode, EDecimal);	
						}
					
					TChar charChar(charCode);
					tmp.Append(charChar);
					tmp.Append(str.Mid(endPos+1));
					str.Copy(tmp);
					}
				}
			// literal constant
			else
				{
				_LIT(KAmp, "amp;");
				_LIT(KQuot, "quot;");
				_LIT(KNbsp, "nbsp;");
				_LIT(KCopy, "copy;");

				// copy start of string
				tmp.Copy(str.Left(startPos));
				if (ptr.CompareF(KAmp) == 0)
					{
					tmp.Append('&');
					}
				else if (ptr.CompareF(KQuot) == 0)
					{
					tmp.Append('"');
					}
				else if (ptr.CompareF(KNbsp) == 0)
					{
					tmp.Append(' ');
					}
				else if (ptr.CompareF(KCopy) == 0)
					{
					tmp.Append('\xA9');
					}
				// copy end of string
				tmp.Append(str.Mid(endPos+1));
				str.Copy(tmp);
				}
			}
		
		if (startPos+1 <= str.Length()) {
			TInt newPos = str.Mid(startPos+1).Locate('&');
			if (newPos != KErrNotFound)
				{
				startPos = startPos+1 + newPos;
				endPos = str.Locate(';');
				}
			else
				{
				startPos = KErrNotFound;
				endPos = KErrNotFound;
				}
			}
		}
	CleanupStack::PopAndDestroy(tmpBuf);
	
	if(str.Length()>1)
		{
		// chop away newlines at start
		DP("    chop away newlines at start");
		while (str.Length() > 0 && (str[0] == KLineBreak))  {
			str = str.Mid(1);
		}
		
		// chop away newlines at end
		DP("    chop away newlines at end");
		while (str.Length() > 0 && (str[str.Length()-1] == KLineBreak)) {
			str = str.Left(str.Length()-1);
		}

		str.Trim();
		}
	DP("PodcastUtils::CleanHtmlL END");
}

EXPORT_C void PodcastUtils::RemoveAllFormatting(TDes & aString)
	{
	// check for combination first so we prevent adding two spaces 
	ReplaceString(aString,_L("\r\n"), _L(" "));
	
	ReplaceString(aString,_L("\n"), _L(" "));
	ReplaceString(aString,_L("\r"), _L(" "));
	
	}

EXPORT_C void PodcastUtils::ReplaceString(TDes & aString, const TDesC& aStringToReplace, const TDesC& aReplacement)
	{
	TInt pos=aString.Find(aStringToReplace);
	TInt offset = 0;
	while (pos != KErrNotFound)
		{
		aString.Replace(offset+pos, aStringToReplace.Length(), aReplacement);
		offset += pos + aStringToReplace.Length()+1;
		if (offset > aString.Length())
			{
			return;
			}

		pos=aString.Mid(offset).Find(aStringToReplace);
		}
	}

EXPORT_C void PodcastUtils::ReplaceChar(TDes & aString, TUint aCharToReplace, TUint aReplacement)
	{
	TInt strLen=aString.Length();
	for (TInt i=0; i < strLen; i++)
		{
		if (aString[i] == aCharToReplace)
			{
			aString[i] = aReplacement;
			}
		}
	}

EXPORT_C void PodcastUtils::EnsureProperPathName(TFileName &aPath)
	{
	// from the SDK: The following characters cannot occur in the path: < >: " / |*
	
	ReplaceChar(aPath, '/', '_'); // better not to add \\ in case we have multiple /
	ReplaceChar(aPath, ':', '_');
	ReplaceChar(aPath, '?', '_');
	ReplaceChar(aPath, '|', '_');
	ReplaceChar(aPath, '*', '_');
	ReplaceChar(aPath, '<', '_');
	ReplaceChar(aPath, '>', '_');
	ReplaceChar(aPath, '"', '_');

	//buf.Append(_L("\\"));
	}

EXPORT_C void PodcastUtils::FileNameFromUrl(const TDesC& aUrl, TFileName &aFileName)
	{
	TInt pos = aUrl.LocateReverse('/');
	
	if (pos != KErrNotFound) 
		{	
		TPtrC str = aUrl.Mid(pos+1);
		pos = str.Locate('?');
		if (pos != KErrNotFound) 
			{
			aFileName.Copy(str.Left(pos));
			} 
		else 
			{
			aFileName.Copy(str);
			}
		}
	DP2("FileNameFromUrl in: %S, out: %S", &aUrl, &aFileName);
	}

EXPORT_C void PodcastUtils::SQLEncode(TDes &aString)
	{
	ReplaceString(aString, _L("\""), _L("\"\""));
	//ReplaceString(aString, _L("'"), _L("''"));	
	}

EXPORT_C void PodcastUtils::XMLEncode(TDes &aString)
	{
	ReplaceString(aString, _L("\""), _L("&quot;"));	
	ReplaceString(aString, _L("<"), _L("&lt;"));
	ReplaceString(aString, _L(">"), _L("&gt;"));
	ReplaceString(aString, _L("&"), _L("&amp;"));
	}

EXPORT_C TBool PodcastUtils::IsVideoShow(TDesC &aUrl)
	{
	if (aUrl.Find(KVideoFormat1) != KErrNotFound ||
			aUrl.Find(KVideoFormat2) != KErrNotFound ||
			aUrl.Find(KVideoFormat3) != KErrNotFound ||
			aUrl.Find(KVideoFormat4) != KErrNotFound)
		{
		return ETrue;
		}

	return EFalse;
	}
