using System;
using System.Text.RegularExpressions;
using System.IO;
using System.Collections;


namespace testEditor
{
	/// <summary>
	/// Summary description for replaceHtml.
	/// </summary>
	public class replaceHtml
	{
		protected static string appPath = "";
		protected static string serverRoot = "";
		protected static string copyPath = "";

		//these two are for saving embed tags which would be romoved in IE (this is just a tempory solution
		//protected static MatchCollection embedColl = null;
		//protected static int objIndex;

		protected const String IMGPATTERN = @"(?<starttag><img[^>]*)src\s*=\s*(?:""|')?(?<imgsrc>[^""']*)(?:""|')?(?<endtag>[^>]*>)";
		
		//<param[^>]* value\s*=\s*(?:\"|\')?(?<flashSrc>[^\"]*.swf)(?:\"|\')?[^>]*>
		protected const String FLASHPATTERN = @"(?<starttag><param[^>]*)value\s*=\s*(?:""|')?(?<flashsrc>[^""']*.swf)(?:""|')?(?<endtag>[^>]*>)";

		//protected const String LINKPATTERN = @"(?<start><a[^>]*)href\s*=\s*(?:""|')?(?<linksrc>[^'"" >]+)(?:""|')?(?<endtag>[^>]*>)";
		
		//need to restrict links here to html/htm file, otherwise the javascript/mailto etc would be changed (add more file types apart from html)
		protected const String LINKPATTERN = @"(?<start><a[^>]*)href\s*=\s*(?:""|')?(?<linksrc>[^'"" >]+.(?:html|htm|doc|pdf|rtf|xls|ppt|txt))(?:""|')?(?<endtag>[^>]*>)";

		protected const String EMBEDPATTERN = @"(?<starttag><embed[^>]*)src\s*=\s*(?:""|')?(?<embedsrc>[^""']*.swf)(?:""|')?(?<endtag>[^>]*>)";

		//this is for capturing the <object></object> for flash objects. The new line \r\n have to be captured
		// or represented using \s*. 
		protected const String OBJPATTERN = @"(?<objstart><object[^>]*?>\s*)(?<objbody>(?:<param[^>]*.swf[^>]*>\s*)+(?:<param[^>]*>\s*)*)</object>";

		protected const String EMBEDONLYPATTERN = @"(?<embedpart><embed[^>]*src\s*=\s*(?:""|')?[^""']*.swf(?:""|')?[^>]*>\s*</embed>\s*)(?<endpart>.{0,10})";


		public replaceHtml()
		{
			//
			// TODO: Add constructor logic here
			//
		}

		public static string getEditorHtml(string htmlSource,string apath)
		{
			appPath = apath;

			/* tempory solutin for keeping the embed tags here, and put them back to html file when the LO 
			 * is saved. Can't deal with any flash object being changed. could recompose the embed tags by
			 * using name/value pair from param tags -- obsolete now

			MatchCollection mc = Regex.Matches(htmlSource,EMBEDPATTERN, RegexOptions.IgnoreCase | RegexOptions.Multiline);
			if (mc.Count > 0)
			{
				embedColl = mc;
				objIndex = 0;
			}
			*/

			//add path for image and flash,no need for links

			htmlSource = Regex.Replace(htmlSource,IMGPATTERN, new MatchEvaluator(addImgPath), RegexOptions.IgnoreCase | RegexOptions.Multiline);

			htmlSource = Regex.Replace(htmlSource,FLASHPATTERN, new MatchEvaluator(addFlashPath), RegexOptions.IgnoreCase | RegexOptions.Multiline); 

			htmlSource = Regex.Replace(htmlSource,EMBEDPATTERN, new MatchEvaluator(addEmbedPath), RegexOptions.IgnoreCase | RegexOptions.Multiline); 

		


			return htmlSource;

			
		}

		public static string getViewHtml(string htmlSource,string apath)
		{
			/* this one is for displaying html web page within current page,
			 * the link path needs to be changed, so does flash path, but not
			 * the image path (? --- do need to change image path)
			 * */

			appPath = apath;
            			
			htmlSource = Regex.Replace(htmlSource,LINKPATTERN, new MatchEvaluator(addLinkPath), RegexOptions.IgnoreCase | RegexOptions.Multiline);

			htmlSource = Regex.Replace(htmlSource,IMGPATTERN, new MatchEvaluator(addImgPath), RegexOptions.IgnoreCase | RegexOptions.Multiline); 

			htmlSource = Regex.Replace(htmlSource,FLASHPATTERN, new MatchEvaluator(addFlashPath), RegexOptions.IgnoreCase | RegexOptions.Multiline); 

			htmlSource = Regex.Replace(htmlSource,EMBEDPATTERN, new MatchEvaluator(addEmbedPath), RegexOptions.IgnoreCase | RegexOptions.Multiline); 

			
			return htmlSource;

		}


		//for saving html back to file
		public static string getStdLOHtml(string editorSource,string apath, string sRoot,string cpath)
		{
			/* to remove the extra path apart from the image file itself
			 * assume there is no subdirectory within the web folder 
			 * */
			appPath = apath;
			serverRoot = sRoot;
			copyPath = cpath;  //only used in copyFile function, for variants case

			editorSource = Regex.Replace(editorSource,IMGPATTERN, new MatchEvaluator(removeImgPath), RegexOptions.IgnoreCase | RegexOptions.Multiline);


			editorSource = Regex.Replace(editorSource,FLASHPATTERN, new MatchEvaluator(removeFlashPath), RegexOptions.IgnoreCase | RegexOptions.Multiline);

			editorSource = Regex.Replace(editorSource,LINKPATTERN, new MatchEvaluator(removeLinkPath), RegexOptions.IgnoreCase | RegexOptions.Multiline);

			editorSource = Regex.Replace(editorSource,EMBEDPATTERN, new MatchEvaluator(removeEmbedPath), RegexOptions.IgnoreCase | RegexOptions.Multiline);

			//for IE, need to put the missing Embed tags back to objects

			editorSource = Regex.Replace(editorSource, OBJPATTERN, new MatchEvaluator(resumeEmbed), RegexOptions.IgnoreCase | RegexOptions.Multiline);

			//important
			//objIndex = 0;
			//embedColl = null;

			editorSource = Regex.Replace(editorSource, EMBEDONLYPATTERN, new MatchEvaluator(composeObj), RegexOptions.IgnoreCase | RegexOptions.Multiline);

			

			return editorSource;

			
		}


		private static string addImgPath(Match m)
		{
			//string upath = "/testEditor/UserFiles/lo1/";  //need to be given value in constructor
			string imgTag = "";
			string newImg = "";
			int pos = m.Groups["imgsrc"].Value.IndexOf("/");
			if (pos < 0)
			{
				imgTag = appPath + m.Groups["imgsrc"].Value;

			}
			else
			{
				int pos2 = m.Groups["imgsrc"].Value.LastIndexOf("/");
				//string imgName = m.Groups["imgsrc"].Value.Substring(pos2+1);
				//imgTag = upath + imgName;

				string subfolder = m.Groups["imgsrc"].Value.Substring(0,pos2);
				if(subfolder.IndexOf(".") < 0 && !subfolder.StartsWith("/"))
				{
					//detect if there is a dot ".", try to avoid the type
					//www.test.com, test.org, etc
					//In this case the link is in the subfolder
					imgTag = appPath + m.Groups["imgsrc"].Value;
				}
				else
				{
					//it would be a url in this case e.g. http://...
					//we would ignore it
					imgTag = m.Groups["imgsrc"].Value;
				}		

			}
			newImg = m.Groups["starttag"].Value + "src=\"" + imgTag + "\"" + m.Groups["endtag"].Value;
			return newImg;
		}



		private static string addLinkPath(Match m)
		{
			//string upath = "/testEditor/UserFiles/lo1/";  
			//need to be given value in constructor, use appPath
			string linkTag = "";
			string newLink = "";
			int pos = m.Groups["linksrc"].Value.IndexOf("/");
			if (pos < 0)
			{
				linkTag = appPath + m.Groups["linksrc"].Value;

			}
			else
			{
				int pos2 = m.Groups["linksrc"].Value.LastIndexOf("/");
				string subfolder = m.Groups["linksrc"].Value.Substring(0,pos2);
				if(subfolder.IndexOf(".") < 0 && !subfolder.StartsWith("/"))
				{
					//detect if there is a dot ".", try to avoid the type
					//www.test.com, test.org, etc
					//In this case the link is in the subfolder
					linkTag = appPath + m.Groups["linksrc"].Value;
				}
				else
				{
					//it would be a url in this case e.g. http://...
					//we would ignore it
					linkTag = m.Groups["linksrc"].Value;
				}		

			}

			newLink = m.Groups["start"].Value + "href=\"" + linkTag + "\"" + m.Groups["endtag"].Value;
			return newLink;
		}



		private static string addFlashPath(Match m)
		{
			//string upath = "/testEditor/UserFiles/lo1/";  //need to be given value in constructor
			string flashTag = "";
			string newflash = "";
			int pos = m.Groups["flashsrc"].Value.IndexOf("/");
			if (pos < 0)
			{
				flashTag = appPath + m.Groups["flashsrc"].Value;

			}
			else
			{
				/** ToDo: consider using a session to keep the orignial path
				 * e.g. session["loname-img"]="../erw/";
				 **/
				int pos2 = m.Groups["flashsrc"].Value.LastIndexOf("/");
				//string flashName = m.Groups["flashsrc"].Value.Substring(pos2+1);
				//flashTag = upath + flashName;
				
				string subfolder = m.Groups["flashsrc"].Value.Substring(0,pos2);
				if(subfolder.IndexOf(".") < 0 && !subfolder.StartsWith("/"))
				{
					//detect if there is a dot ".", try to avoid the type
					//www.test.com, test.org, etc
					//In this case the link is in the subfolder
					flashTag = appPath + m.Groups["flashsrc"].Value;
				}
				else
				{
					//it would be a url in this case e.g. http://...
					//we would ignore it
					flashTag = m.Groups["flashsrc"].Value;
				}		

			}
			newflash = m.Groups["starttag"].Value + "value=\"" + flashTag + "\"" + m.Groups["endtag"].Value;
			return newflash;
		}



		private static string addEmbedPath(Match m)
		{
			
			string embedTag = "";
			string newembed = "";
			int pos = m.Groups["embedsrc"].Value.IndexOf("/");
			if (pos < 0)
			{
				embedTag = appPath + m.Groups["embedsrc"].Value;

			}
			else
			{
				
				int pos2 = m.Groups["embedsrc"].Value.LastIndexOf("/");
								
				string subfolder = m.Groups["embedsrc"].Value.Substring(0,pos2);
				if(subfolder.IndexOf(".") < 0 && !subfolder.StartsWith("/"))
				{
					//detect if there is a dot ".", try to avoid the type
					//www.test.com, test.org, etc
					//In this case the link is in the subfolder
					embedTag = appPath + m.Groups["embedsrc"].Value;
				}
				else
				{
					//it would be a url in this case e.g. http://...
					//we would ignore it
					embedTag = m.Groups["embedsrc"].Value;
				}		

			}
			newembed = m.Groups["starttag"].Value + "src=\"" + embedTag + "\"" + m.Groups["endtag"].Value;
			return newembed;
		}



		private static string removeImgPath(Match m)
		{
			string imgFolder = System.Configuration.ConfigurationSettings.AppSettings["FCKeditor:UserFilesPath"] + "Image/";
			string imgTag = "";
			string newImg = "";
			int pos = m.Groups["imgsrc"].Value.IndexOf(appPath);
			if (pos < 0)
			{
				string imgLink = m.Groups["imgsrc"].Value;
				//this is the case when user add image via the editor interface, the image
				//would be save to UserFiles/Image/ folder initially. So the image will need
				//to be copied to the LO folder itself for exporting purpuse
				if(imgLink.StartsWith(imgFolder))
				{
					copyFiles(imgLink);
					imgTag = imgLink.Substring(imgLink.LastIndexOf("/")+1);
				}
				else
				{
					imgTag = imgLink;  //keep the same
				}


			}
			else
			{
				//int pos2 = m.Groups["imgsrc"].Value.LastIndexOf("/");
				//imgName might include subfolder path
				string imgName = m.Groups["imgsrc"].Value.Substring(appPath.Length);
				imgTag = imgName;

			}
			newImg = m.Groups["starttag"].Value + "src=\"" + imgTag + "\"" + m.Groups["endtag"].Value;
			return newImg;
		}


		private static void copyFiles(string currLink)
		{
			string originalPath = serverRoot + currLink.Replace("/", "\\");
			string destiPath = serverRoot + copyPath.Replace("/", "\\") + currLink.Substring(currLink.LastIndexOf("/")+1);
			File.Copy(originalPath,destiPath,true);
		}




		private static string removeFlashPath(Match m)
		{
			
			string flashTag = "";
			string newFlash = "";
			int pos = m.Groups["flashsrc"].Value.IndexOf(appPath);
			if (pos < 0)
			{
				
				flashTag = m.Groups["flashsrc"].Value;  //keep the same
				
			}
			else
			{
				//int pos2 = m.Groups["flashsrc"].Value.LastIndexOf("/");
				string flashName = m.Groups["flashsrc"].Value.Substring(appPath.Length);
				flashTag = flashName;
			}

			newFlash = m.Groups["starttag"].Value + "value=\"" + flashTag + "\"" + m.Groups["endtag"].Value;
			return newFlash;
		}


		private static string removeEmbedPath(Match m)
		{
			string flashFolder = System.Configuration.ConfigurationSettings.AppSettings["FCKeditor:UserFilesPath"] + "Flash/";
			string embedTag = "";
			string newembed = "";
			int pos = m.Groups["embedsrc"].Value.IndexOf(appPath);
			if (pos < 0)
			{
				string flashLink = m.Groups["embedsrc"].Value; 
				//this is the case when user add flash via the editor interface, the flash
				//would be save to UserFiles/Flash/ folder initially. So the flash will need
				//to be copied to the LO folder itself for exporting purpuse
				if(flashLink.StartsWith(flashFolder))
				{
					copyFiles(flashLink);
					//get the name of the flash file
					embedTag = flashLink.Substring(flashLink.LastIndexOf("/")+1);
				}
				else
				{
					embedTag = flashLink;  //keep the same
				}

			}
			else
			{
				//int pos2 = m.Groups["flashsrc"].Value.LastIndexOf("/");
				string embedName = m.Groups["embedsrc"].Value.Substring(appPath.Length);
				embedTag = embedName;
			}

			newembed = m.Groups["starttag"].Value + "src=\"" + embedTag + "\"" + m.Groups["endtag"].Value;
			return newembed;
		}


		private static string removeLinkPath(Match m)
		{
			string fileFolder = System.Configuration.ConfigurationSettings.AppSettings["FCKeditor:UserFilesPath"] + "File/";
			string linkTag = "";
			string newLink = "";
			int pos = m.Groups["linksrc"].Value.IndexOf(appPath);
			if (pos < 0)
			{
				string fileLink = m.Groups["linksrc"].Value; 
				//this is the case when user add flash via the editor interface, the flash
				//would be save to UserFiles/Flash/ folder initially. So the flash will need
				//to be copied to the LO folder itself for exporting purpuse
				if(fileLink.StartsWith(fileFolder))
				{
					copyFiles(fileLink);
					//get the name of the file
					linkTag = fileLink.Substring(fileLink.LastIndexOf("/")+1);
				}
				else
				{
					linkTag = fileLink;  //keep the same
				}

			}
			else
			{
				
				string linkName = m.Groups["linksrc"].Value.Substring(appPath.Length);
				linkTag = linkName;

			}
			newLink = m.Groups["start"].Value + "href=\"" + linkTag + "\"" + m.Groups["endtag"].Value;
			
			return newLink;
		}


		private static string resumeEmbed(Match m)
		{
			string embedTag = "";
			string newObj = "";
			string objcontent = m.ToString();
			Match mEmbed = Regex.Match(objcontent,EMBEDPATTERN,RegexOptions.IgnoreCase | RegexOptions.Multiline);
			
			string objBody = m.Groups["objbody"].Value;

			if (!mEmbed.Success)
			{
				//embedTag = embedColl[objIndex].ToString();

				/* the method is to compose embed tag by using those key/vaule sets in object
				 * and params tags, instead of the previous method of recovering the original */

				embedTag = composeEmbedTag(objcontent,objBody);
				
			}
			
			newObj = m.Groups["objstart"].Value + m.Groups["objbody"].Value + embedTag + "</object>";
			//objIndex++;  //important
			return newObj;

		}


		private static string composeObj(Match m)
		{
			string endpart = m.Groups["endpart"].Value;
			//if (endpart.IndexOf("</embed></object>") >= 0)
			//	return m.Value;

			String ENDPATTERN = @"\s*</object>\s*.*";
			Match mend = Regex.Match(endpart,ENDPATTERN,RegexOptions.IgnoreCase | RegexOptions.Multiline); 
			if (mend.Success)
			{
				return m.Value;
			}

			string objTags = addObjTag(m.Groups["embedpart"].Value);
			objTags = objTags + m.Groups["embedpart"].Value + "</object>" + endpart;
			return objTags;
			
		}


		private static string composeEmbedTag(string objStr, string objbody)
		{

			String PARAMPATTERN1 = @"<param[^>]*name\s*=\s*(?:""|')?(?<name>[^""']*)(?:""|')?\s*value\s*=\s*(?:""|')?(?<value>[^""']*)(?:""|')?[^>]*>";
			String PARAMPATTERN2 = @"<param[^>]*value\s*=\s*(?:""|')?(?<value>[^""']*)(?:""|')?\s*name\s*=\s*(?:""|')?(?<name>[^""']*)(?:""|')?[^>]*>";

			String OBJWIDTH = @"<object[^>]*width\s*=\s*(?:""|')?(?<width>[^""']*)(?:""|')?[^>]*>";
			String OBJHEIGHT = @"<object[^>]*height\s*=\s*(?:""|')?(?<height>[^""']*)(?:""|')?[^>]*>";
			String OBJALIGN = @"<object[^>]*align\s*=\s*(?:""|')?(?<align>[^""']*)(?:""|')?[^>]*>";

			string embedStr = "<embed";

			MatchCollection mcParam1 = Regex.Matches(objbody,PARAMPATTERN1, RegexOptions.IgnoreCase | RegexOptions.Multiline);
			if (mcParam1.Count > 0 )
			{ 
				for (int i=0; i<mcParam1.Count; i++)
				{
					string iName = mcParam1[i].Groups["name"].Value;
					string iValue = mcParam1[i].Groups["value"].Value;
					if (iName == "movie" && iValue.IndexOf("swf") >= 0)
					{
						embedStr += " src=\"" + iValue + "\"";
					}
					else
					{
						embedStr += " " + iName + "=\"" + iValue + "\"";
					}
				}

			}

			MatchCollection mcParam2 = Regex.Matches(objbody,PARAMPATTERN2, RegexOptions.IgnoreCase | RegexOptions.Multiline);
			if (mcParam2.Count > 0 )
			{ 
				for (int i=0; i<mcParam2.Count; i++)
				{
					string iName = mcParam2[i].Groups["name"].Value;
					string iValue = mcParam2[i].Groups["value"].Value;
					if (iName == "movie" && iValue.IndexOf("swf") >= 0)
					{
						embedStr += " src=\"" + iValue + "\"";
					}
					else
					{
						embedStr += " " + iName + "=\"" + iValue + "\"";
					}

				}
			}

			Match mwidth = Regex.Match(objStr,OBJWIDTH,RegexOptions.IgnoreCase | RegexOptions.Multiline);
			if (mwidth.Success)
			{
				embedStr += " width=\"" + mwidth.Groups["width"].Value + "\"";
			}

			Match mheight = Regex.Match(objStr,OBJHEIGHT,RegexOptions.IgnoreCase | RegexOptions.Multiline);
			if (mheight.Success)
			{
				embedStr += " height=\"" + mheight.Groups["height"].Value + "\"";
			}

			Match malign = Regex.Match(objStr,OBJALIGN,RegexOptions.IgnoreCase | RegexOptions.Multiline);
			if (malign.Success)
			{
				embedStr += " align=\"" + malign.Groups["align"].Value + "\"";
			}

			embedStr += " pluginspage=\"http://www.macromedia.com/go/getflashplayer\" type=\"application/x-shockwave-flash\"></embed>";

			return embedStr;

		}


		private static string addObjTag(string embedStr)
		{
			
			//String PATTERN1 = @"(?<key>\w*)\s*=\s*(?:""|')?(?<value>[^""']*)(?:""|')? | [^\s]+";
			String PATTERN1 = @"(?<key>\w*)\s*=\s*(?:""|')?(?<value>[^""']*)(?:""|')?";
			string embedCont = embedStr.Substring(6,embedStr.IndexOf(">")-6).Trim();

			MatchCollection mc = Regex.Matches(embedCont,PATTERN1, RegexOptions.IgnoreCase | RegexOptions.Multiline);

			/* classid seems very important to be there for the flash to be displayed in 
			 * the editor, how to get the classid? 
			 * */
			string objStr = "<object codebase=\"http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,29,0\" classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"";
			ArrayList paramList = new ArrayList();

			if (mc.Count > 0)
			{
				
				for (int i=0; i<mc.Count; i++)
				{
					string ikey = mc[i].Groups["key"].Value;
					string ivalue = mc[i].Groups["value"].Value;
					string iparam = "";

					switch (ikey.ToLower())
					{
						case "width":						
						case "height":
						case "align":
							objStr += " " + ikey + "=\"" + ivalue + "\"";
							break;
						case "src":
							iparam = "<param name=\"movie\" value=\"" + ivalue + "\" />";
							paramList.Add(iparam);
							break;
						case "pluginspage":
						case "type":
							break;
						default:
							iparam = "<param name=\"" + ikey + "\" value=\"" + ivalue + "\" />";
							paramList.Add(iparam);
							break;
					}
				}
				objStr += ">";

				for(int j=0; j<paramList.Count; j++)
				{
					objStr += paramList[j].ToString();
				}					
			}
			

			return objStr;
		}



		public static string getNewText(string pth)
		{

			Regex ew = new Regex(@"<img[^>]* src\s*=\s*(?<imgSrc>[^""]*)[^>]*>");
			//string p18 = @"<A[^>]*?HREF\s*=\s*[""']?([^'"" >]+?)[ '""]?>";
			string test1 = @"<img width=5 src=""test.jpg"">"; 

			appPath = pth;

			string str = changeTxt();
			return str;

           }


			private static string changeTxt()
			{
				string txt = appPath + "/test/";
				return txt;

							
			}


			
		
	}
}
