using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using iTextSharp.text.pdf;
using iTextSharp.text;
using VEPROMS.CSLA.Library;
namespace Volian.Print.Library
{
	public partial class vlnTab : vlnText
	{
		/// 
		/// Used to Align Tabs for numeric tabs that can go to 2 digits
		/// 
		private float? _TabAlign;
		public float TabAlign // Offset to Last printable character
		{
			get
			{
				if (_TabAlign == null)
				{
					_TabAlign = 0;
					if (Text != null && (!MyParent.MyItemInfo.IsStep || !MyParent.MyItemInfo.FormatStepData.TabData.NoTabAlign))
					{
						while (_TabAlign < Text.Length && Text[(int)_TabAlign] == ' ')
							_TabAlign++;
						if (_TabAlign < Text.Length)
						{
							if ("0123456789".Contains(Text[(int)_TabAlign].ToString()))
							{
								while ("0123456789".Contains(Text[(int)_TabAlign].ToString()))
									_TabAlign++;
								_TabAlign--;
							}
						}
						else
							_TabAlign = 0;
					}
				}
				return (float)_TabAlign * MyFont.CharsToTwips;
			}
		}
		private float? _TabOffset;
		public float TabOffset // Offset to first printable character
		{
			get
			{
				if (_TabOffset == null)
				{
					_TabOffset = 0;
					if (Text != null)
					{
						while (_TabOffset= Text.Length) _TabOffset = 0;
				return (float)_TabOffset * MyFont.CharsToTwips;
			}
		}
		private vlnMacro _MyMacro;
		public vlnMacro MyMacro
		{
			get { return _MyMacro; }
			set { _MyMacro = value; }
		}
		private string symblsStr = "\u25CF\u0394"; // string of possible symbol character in a tab
											 // add symbol characters as needed
											 // "\u25CF" - solid bullet
											 // \x0394 - delta
		private System.Drawing.FontStyle GetSysFontStyle(VE_Font f)
		{
			if (f.Style == E_Style.Italics)
				return System.Drawing.FontStyle.Italic;
			return FontStyle.Regular;
		}
		public float GetTextWidth(VE_Font vefont, string txt)
		{
			return GetTextWidth(vefont, txt, SymbolFontName);
		}
		private float GetTextWidth(VE_Font vefont, string txt, string symblFontName)
		{
			System.Drawing.Font font = new System.Drawing.Font(vefont.Family, (float)vefont.Size, GetSysFontStyle(vefont));
			System.Drawing.Font symbFont = new System.Drawing.Font(symblFontName, (float)vefont.Size);
			iTextSharp.text.Font iFont = Volian.Svg.Library.VolianPdf.GetFont(font);
			iTextSharp.text.Font iSymblFont = Volian.Svg.Library.VolianPdf.GetFont(symbFont);
			float w = 0;
			foreach (char c in txt)
			{
				int idx = symblsStr.IndexOf(c);
				if (idx >= 0) // symbol character - use symbol font to find its width
					w += iSymblFont.BaseFont.GetWidthPointKerned(symblsStr[idx].ToString(), (float)vefont.Size);
				else
					w += iFont.BaseFont.GetWidthPointKerned(c.ToString(), (float)vefont.Size);
			}
			//float w = iFont.BaseFont.GetWidthPointKerned(Text.Replace("\u25CF","@"), (float)vefont.Size);
			return w;
		}
		bool _ScriptCaution = false;
		public bool ScriptCaution
		{
			get { return _ScriptCaution; }
			set { _ScriptCaution = value; }
		}
		bool _SeparateBullet = false;
		public bool SeparateBullet
		{
			get { return _SeparateBullet; }
			set { _SeparateBullet = value; }
		}
		private string _SymbolFontName;
		public string SymbolFontName
		{
			get { return _SymbolFontName; }
			set { _SymbolFontName = value; }
		}
		public vlnTab(PdfContentByte cb, vlnParagraph myparent, string origTab, string cleanTab, float xoffset, float yoffset, VE_Font vFont, bool doSectTab, string symblFontName, bool removedUnderline)
		{
			SymbolFontName = symblFontName;
			bool alignAsIfBulleted = false;
			ScriptCaution = (origTab.Contains("Caution") && vFont.Family == "VolianScript");
			MyContentByte = cb;
			MyParent = myparent;
			YOffset = yoffset;
			Text = cleanTab;
			MyFont = vFont;
			// BGE has a format flag to increase size of font, if top level:
			if (doSectTab && myparent.MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.SectionNumber.Level0Big && myparent.MyItemInfo.MyParent.IsProcedure)
				vFont = new VE_Font(vFont.Family, 14, (E_Style)vFont.Style | E_Style.Bold, 8);
			float CCCs = GetTextWidth(MyFont, "CCCCCCCCCC", symblFontName);
			float IIIs = GetTextWidth(MyFont, "iiiiiiiiii", symblFontName);
			string origTab1 = origTab;
			if (ScriptCaution)
			{
				Text = origTab.Replace("Caution  ", "\uF043\uF061\uF069\uF06E\uF06F\uF074\uF075\uF020\uF020");
				Width = 90;
			}
			else if ((myparent.MyItemInfo.FormatStepData != null) && (myparent.MyItemInfo.FormatStepData.TabData.IdentWidth ?? 0) > 0)
				//if ((myparent.MyItemInfo.FormatStepData != null) && (myparent.MyItemInfo.FormatStepData.TabData.IdentWidth ?? 0) > 0)
				Width = (float)myparent.MyItemInfo.FormatStepData.TabData.IdentWidth;
			else if (CCCs != IIIs)
			{
				float tPtPerChar = myparent.MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.TabPtsPerChar ?? 6;
				Width = (tPtPerChar == 0 ? 6 : tPtPerChar) * origTab.Length;
				// Check the following, it may be needed for FPL:
				//origTab1 = origTab1.TrimStart(" ".ToCharArray());
				// 6 = number of points per character.  4 characters between end of tab and beginning of text
				//   origTab1.Trim... is number of non-space characters of the tab string.
				//Width = 6 * (4 + origTab1.Trim(" ".ToCharArray()).Length);
			}
			else
				Width = GetTextWidth(MyFont, (Text != null ? Text : origTab), symblFontName); //MyFont.CharsToTwips * (Text != null ? Text.Length : origTab.Length);
			// Pairie Island (NSP) Caution and Note tabs use a larger font
			// When using a bullet, we need to use the font size of the Caution/Note text instead of the tab.
			// To do this we set the TabData.Bullet.Separate to true (currently - 4/26/2013 - only NSP uses this).
			// Because of the different font sizes, when the Caution/Note did have have a bullet, the positioning 
			// was off by the lenght of IdentB (the bullet string), thus the "alignAsIfBulleted" bool
			if ((myparent.MyItemInfo.FormatStepData != null) && myparent.MyItemInfo.FormatStepData.TabData.Bullet.Separate)
				if (myparent.MyItemInfo.MyPrevious != null || myparent.MyItemInfo.NextItem != null)
					SeparateBullet = true;
				else
					alignAsIfBulleted = true;
			if (origTab.Contains(@"{!"))
			{
				int mindx = origTab.IndexOf(@"{!");
				int meindx = origTab.IndexOf(@"}", mindx);
				string macro = origTab.Substring(mindx, meindx - mindx + 1);
				// Width for placement of macro should be position in the string where the macro was located.
				float lwidth = MyFont.CharsToTwips * (origTab.Length - meindx - 1);
				MyMacro = new vlnMacro(xoffset - lwidth, yoffset, macro.Substring(2, macro.Length - 3));
				xoffset += myparent.MyItemInfo.FormatStepData.TabData.MacroTabAdjust ?? 0;
				origTab = origTab.Replace(macro, "");
				cleanTab = origTab;
				if (CCCs != IIIs)
				{
					float? tPtPerChar1 = myparent.MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.TabPtsPerChar;
					if (tPtPerChar1 != null)
						Width = (float)tPtPerChar1 * origTab.Length;
					else if ((myparent.MyItemInfo.FormatStepData != null) && (myparent.MyItemInfo.FormatStepData.TabData.IdentWidth ?? 0) > 0)
						Width = (float)myparent.MyItemInfo.FormatStepData.TabData.IdentWidth;
					else
					{
						origTab = origTab + " ";
						origTab = origTab.TrimStart(" ".ToCharArray());
						if (mindx > 2) // ouch!
							Width = 6f * (origTab.Length - 1); // FPL (macro is after {numeric})  FPL is good with genmac output!
						else
							Width = 3 + (6f * origTab.Length); // NSP (macro is before {numeric})
					}
				}
				else
					Width = GetTextWidth(MyFont, (cleanTab != null ? cleanTab : origTab), symblFontName);//MyFont.CharsToTwips * (cleanTab != null ? cleanTab.Length : origTab.Length);
			}
			else
			{
				origTab = origTab1;
			}
			// if this tab was underlined, we may need to add partial underlining back in, if it was
			// removed when the bullet was added. This handles the case where the bullet was appended 
			// to the tab, for example  "NOTE:  o".  
			if (removedUnderline)
			{
				int sep = origTab.IndexOfAny(". ".ToCharArray());
				string prefix = ((vFont.Style & E_Style.Bold) > 0) ? @"\b\ul " : @"\ul ";
				string suffix = ((vFont.Style & E_Style.Bold) > 0) ? @"\b0\ulnone " : @"\ulnone ";
				//origTab = @"\ul " + origTab.Substring(0, sep-1) + @"\ulnone" + origTab.Substring(sep-1);
				//origTab = @"\ul " + origTab.Substring(0, sep) + @"\ulnone" + origTab.Substring(sep);
				origTab = prefix + origTab.Substring(0, sep) + suffix + origTab.Substring(sep);
			}
			UnderlineTerminateList utl = myparent.MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.UnderlineTerminateList;
			// if this tab is underlined, the underlining should not underline the ':'. Check for "NOTE:"
			// or "CAUTION:", i.e. only underline up to ':'
			if (myparent.MyItemInfo.IsStep && ((myparent.MyItemInfo.FormatStepData.AlwaysTab || myparent.MyItemInfo.MyPrevious == null)
				&& ((vFont.Style & E_Style.Underline) > 0) && (origTab.ToUpper().Contains("NOTE:") ||
				origTab.ToUpper().Contains("CAUTION:"))))
			{
				FontStyle style = FontStyle.Regular;
				if ((vFont.Style & E_Style.Bold) > 0) style |= FontStyle.Bold;
				if ((vFont.Style & E_Style.Italics) > 0) style |= FontStyle.Italic;
				vFont.WindowsFont = new System.Drawing.Font(vFont.Family, (float)vFont.Size, style);
				int indxC = origTab.IndexOf(":");
				origTab = @"\ul " + origTab.Substring(0, indxC) + @"\ulnone" + origTab.Substring(indxC);
			}
			else if (utl != null && utl.Count > 0 && ((vFont.Style & E_Style.Underline) > 0))
			{
				foreach (UnderlineTerminate ut in utl)
				{
					if (origTab.Contains(ut.Text))
					{
						FontStyle style = FontStyle.Regular;
						if ((vFont.Style & E_Style.Bold) > 0) style |= FontStyle.Bold;
						if ((vFont.Style & E_Style.Italics) > 0) style |= FontStyle.Italic;
						vFont.WindowsFont = new System.Drawing.Font(vFont.Family, (float)vFont.Size, style);
						int indxC = origTab.IndexOf(ut.Text);
						string prefix = ((vFont.Style & E_Style.Bold) > 0) ? @"\b\ul " : @"\ul ";
						string suffix = ((vFont.Style & E_Style.Bold) > 0) ? @"\b0\ulnone " : @"\ulnone ";
						//origTab = @"\ul " + origTab.Substring(0, indxC) + @"\ulnone " + origTab.Substring(indxC);
						origTab = prefix + origTab.Substring(0, indxC) + suffix + origTab.Substring(indxC);
						break;
					}
				}
			}
			Rtf = GetRtf(origTab, vFont);
			Rtf = Rtf.Replace("\u0394", @"\f1\u916?\f0 ");		// delta 0x0394
			if (ScriptCaution)
			{
				Rtf = GetRtf("\u25CFCaution  ", vFont);
				Rtf = Rtf.Replace("\u25CF", @"\f1\fs20              \u9679?\f0\par\f0\fs64 ");		// bullet 25CF // jsj- force bullet size (is different than tab text)
				if (myparent.MyItemInfo.FormatStepData != null && !myparent.MyItemInfo.FormatStepData.AlwaysTab && myparent.MyItemInfo.MyPrevious != null)
					Rtf = Rtf.Replace("Caution  ", @"\u61472?\u61472?\u61472?\u61472?\u61472?\u61472?\u61472?\u61472?\u61472?");
				else
				{
					if (myparent.MyItemInfo.FormatStepData != null && !myparent.MyItemInfo.FormatStepData.AlwaysTab && myparent.MyItemInfo.NextItem == null)
						Rtf = Rtf.Replace(@"\u9679?", "");
					Rtf = Rtf.Replace("Caution  ", @"\u61507?\u61537?\u61557?\u61556?\u61545?\u61551?\u61550?\u61472?\u61472?");
				}
			}
			else
			{
				if (SeparateBullet)
					Rtf = Rtf.Replace("\u25CF", "");
				else
					Rtf = Rtf.Replace("\u25CF", @"\f1\u9679?\f0 ");		// bullet 25CF // jsj- add space after \f0
				//Rtf = Rtf.Replace("\u25CF", @"\f1\fs18\b0\i0        \u9679?\f0 ");		// bullet 25CF // jsj- add space after \f0
				if (myparent.MyItemInfo.FormatStepData != null && !myparent.MyItemInfo.FormatStepData.AlwaysTab && myparent.MyItemInfo.MyPrevious != null &&
					(!myparent.MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.OnlyBulletSameCautionNoteType ||
					(myparent.MyItemInfo.MyPrevious.MyContent.Type == myparent.MyItemInfo.MyContent.Type)))
				{
					//if (scriptCaution)
					//    Rtf = Rtf.Replace("CAUTION  ", @"\u61472?\u61472?\u61472?\u61472?\u61472?\u61472?\u61472?\u61472?\u61472?");
					Rtf = Rtf.Replace("Caution:", "        ");
					Rtf = Rtf.Replace("Note:", "     ");
					Rtf = Rtf.Replace("CAUTION:", "        ");
					Rtf = Rtf.Replace("NOTE:", "     ");
					Rtf = Rtf.Replace("Caution", "       ");
					Rtf = Rtf.Replace("Note", "    ");
					Rtf = Rtf.Replace("CAUTION", "       ");
					Rtf = Rtf.Replace("NOTE", "    ");
				}
			}
			//if (ScriptCaution && Rtf.Contains("Caution"))
			//{
			//    // NSP script caution
			//    iTextSharp.text.Font myfont = pdf.GetFont(vFont.Family, 28, 0, iTextSharp.text.Color.BLACK);
			//    if (!myfont.BaseFont.CharExists(0x43)) // Capital 'C' exists as text
			//    {
			//        //VE_Font vf = new VE_Font("VolianScript", 28, E_Style.Italics, 12);
			//        // Capital 'C' exists as Symbol
			//        Rtf = Rtf.Replace("Caution  ", @"\u61507?\u61537?\u61557?\u61556?\u61545?\u61551?\u61550?\u61472?\u61472?");
			//    }
			//}
			// do positioning based on whether format has locations for section 'header'.  If it's not centered, treat
			// it's location more like a 'tab'.
			if (doSectTab)
			{
				XOffset = xoffset;
				// the width was just a little small, so it was wrapping - but only if there were no spaces at end
				// so use this condition to do minimal impact  (WCN1 format, for section tabs with three places, i.e. 6.1.2
				if (!cleanTab.EndsWith(" ")) Width += .1f;
			}
			else
			{
				// if using a proportional font and the tab font/size is different than the text font/size
				if (CCCs != IIIs &&
					(MyFont.Family != myparent.MyItemInfo.FormatStepData.Font.Family ||
					MyFont.Size != myparent.MyItemInfo.FormatStepData.Font.Size))
				{
					// This is needed for Prairie Island (NSP) Caution/Note tabs to consistantly position
					// them at the same horizontal (column) position on the page
					string txt = Text;
					if (alignAsIfBulleted)
						txt += myparent.MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.IdentB;
					System.Drawing.Font font = new System.Drawing.Font(MyFont.Family, (float)MyFont.Size);
					iTextSharp.text.Font iFont = Volian.Svg.Library.VolianPdf.GetFont(font);
					float w = iFont.BaseFont.GetWidthPointKerned(txt, (float)MyFont.Size);
					Width = w;
				}
				XOffset = xoffset - Width;
			}
		}
		public override float ToPdf(PdfContentByte cb, float yPageStart, ref float yTopMargin, ref float yBottomMargin)
		{
			if (MyParent.MyItemInfo.FormatStepData != null && MyParent.MyItemInfo.FormatStepData.StepPrintData != null) 
				XOffset += (float)(MyParent.MyItemInfo.FormatStepData.StepPrintData.PosAdjust ?? 0);
			float yLocation = CalculateYOffset(yPageStart, yTopMargin);
			Rtf2Pdf.TextAt(cb, IParagraph, XOffset, yLocation, Width, 100, "", yBottomMargin);
			return yPageStart;
		}
	}
}