using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using iTextSharp.text.pdf;
using iTextSharp.text.factories;
using Microsoft.Win32;

namespace VG
{
	public interface IVGOutput
	{
		float Scale { get;}
		int DebugStatus { get; set; }
		void DrawLine(Pen pn, float startx, float starty, float endx, float endy);
		void DrawRectangle(Pen pn, RectangleF rectf);
		void DrawEllipse(Pen pn, float cx, float cy, float dx, float dy);
		void DrawImage(Bitmap bm, RectangleF rectf);
		void DrawString(string text, Font myFont, Brush brush, RectangleF rectf);
		void DrawArc(Pen pn, RectangleF rectf, float startAngle, float sweepAngle);
		SizeF MeasureString(string text, Font myFont);
		void Save(string fileName);
		float FontSizeAdjust { get;}
	}
	public partial class VGOut_Graphics: IVGOutput
	{
		private int _DebugStatus = 0;
		public int DebugStatus
		{
			get { return _DebugStatus; }
			set { _DebugStatus = value; }
		}
		private Graphics _VGOutput;
		//public Graphics VGOutput
		//{ get { return _VGOutput; } }
		public VGOut_Graphics(Graphics vgOutput)
		{ _VGOutput = vgOutput; }
		public float Scale
		{ get { return 1; } }
		//{ get { return _VGOutput.Transform.Elements[0]; } }
		public void DrawLine(Pen pn, float startx, float starty, float endx, float endy)
		{ _VGOutput.DrawLine(pn, startx, starty, endx, endy);	}
		public void DrawRectangle(Pen pn, RectangleF rectf)
		{
			_VGOutput.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;
			_VGOutput.FillRectangle(DebugStatus == 1 ? Brushes.Transparent : Brushes.White, rectf.X, rectf.Y, rectf.Width, rectf.Height);
			_VGOutput.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver;
			_VGOutput.DrawRectangle(pn, rectf.X, rectf.Y, rectf.Width, rectf.Height); 
		}
		public void DrawEllipse(Pen pn, float cx, float cy, float dx, float dy)
		{ _VGOutput.DrawEllipse(pn, cx, cy, dx, dy); }
		public void DrawImage(Bitmap bm, RectangleF rectf)
		{ _VGOutput.DrawImage(bm, rectf); }
		public void DrawString(string text, Font myFont, Brush brush, RectangleF rectf)
		{ _VGOutput.DrawString(text, myFont, brush, rectf, StringFormat.GenericTypographic); }
		public void DrawArc(Pen pn, RectangleF rectf, float startAngle, float sweepAngle)
		{ _VGOutput.DrawArc(pn, rectf, startAngle, sweepAngle); }
		public SizeF MeasureString(string text, Font myFont)
		{ return _VGOutput.MeasureString(text, myFont, new PointF(0, 0), StringFormat.GenericTypographic); }
		public void Save(string fileName)
		{ ;/* Don't do anything*/ }
		public float FontSizeAdjust
		{ get { return .71f * 96f / _VGOutput.DpiX; } } // Changed to adjust for Screen DPI Setting
	}
	public partial class VGOut_ITextSharp : IVGOutput
	{
		private int _DebugStatus = 0;
		public int DebugStatus
		{
			get { return _DebugStatus; }
			set { _DebugStatus = value; }
		}
		private PdfContentByte _VGOutput;
		//public Graphics VGOutput
		//{ get { return _VGOutput; } }
		public VGOut_ITextSharp(PdfContentByte vgOutput)
		{ _VGOutput = vgOutput; }
		public float Scale
		{ get { return 1; } }
		public void DrawLine(Pen pn, float startx, float starty, float endx, float endy)
		{
			_VGOutput.SaveState();
			SetStrokeData(pn);
			_VGOutput.MoveTo(startx, ScaleY(starty));
			_VGOutput.LineTo(endx, ScaleY(endy));
			_VGOutput.Stroke();
			_VGOutput.RestoreState();
		}
		private void SetStrokeData(Pen pn)
		{
			_VGOutput.SetLineWidth(pn.Width);
			_VGOutput.SetColorStroke(new iTextSharp.text.Color(pn.Color.R, pn.Color.G, pn.Color.B, pn.Color.A));
		}
		public void DrawRectangle(Pen pn, RectangleF rectf)
		{
			_VGOutput.SaveState();
			SetStrokeData(pn);
			_VGOutput.Rectangle(rectf.X, ScaleY(rectf.Y), rectf.Width, -rectf.Height);
			_VGOutput.Stroke();
			_VGOutput.RestoreState();
		}
		public void DrawEllipse(Pen pn, float cx, float cy, float dx, float dy)
		{
			_VGOutput.SaveState();
			SetStrokeData(pn);
			_VGOutput.Ellipse(cx, ScaleY(cy), dx, -dy);
			_VGOutput.Stroke();
			_VGOutput.RestoreState();
		}
		public void DrawImage(Bitmap bm, RectangleF rectf)
		{
			_VGOutput.SaveState();
			// TODO: Determine how I can create an iTextSharp.text.Image
			//_VGOutput.AddImage(new iTextSharp.text.Image(
			_VGOutput.RestoreState();
		}
		public void DrawString(string text, Font myFont, Brush brush, RectangleF rectf)
		{
			_VGOutput.SaveState();
			_VGOutput.BeginText();
			iTextSharp.text.Font itFont = GetFont(myFont.Name);
			iTextSharp.text.pdf.BaseFont baseFont = itFont.BaseFont;
	//    _VGOutput.DrawString(text, myFont, brush, rectf, StringFormat.GenericTypographic); 
			_VGOutput.MoveText(rectf.X, ScaleY(rectf.Y) - myFont.SizeInPoints);
			_VGOutput.SetFontAndSize(baseFont, myFont.SizeInPoints);
			_VGOutput.SetTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_FILL);
			_VGOutput.ShowTextKerned(text);
			_VGOutput.EndText();
			_VGOutput.RestoreState();
		}
		public void DrawArc(Pen pn, RectangleF rectf, float startAngle, float sweepAngle)
		{
			_VGOutput.SaveState();
			SetStrokeData(pn);
			_VGOutput.Arc(rectf.X, ScaleY(rectf.Y), rectf.X + rectf.Width, ScaleY(rectf.Y + rectf.Height), -startAngle, -sweepAngle);
			_VGOutput.Stroke();
			_VGOutput.RestoreState();
		}
		public SizeF MeasureString(string text, Font myFont)
		{
			iTextSharp.text.Font itFont = GetFont(myFont.Name);
			iTextSharp.text.pdf.BaseFont baseFont = itFont.BaseFont;
			return new SizeF(baseFont.GetWidthPoint(text,myFont.SizeInPoints)
				, baseFont.GetAscentPoint(text, myFont.SizeInPoints) + baseFont.GetDescentPoint(text, myFont.SizeInPoints));
		}
		public void Save(string fileName)
		{ ;/* Don't do anything*/ }
		public float FontSizeAdjust
		{ get { return 1; } } // Changed to adjust for Screen DPI Setting
		public static iTextSharp.text.Font GetFont(string fontName)
		{
			RegisterFont(fontName);
			return iTextSharp.text.FontFactory.GetFont(fontName, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
		}
		//private void RegisterFonts()
	//  {
		//  //if (!FontFactory.IsRegistered("Arial"))
		//  //{
		//  //  RegisterFont("Prestige Elite Tall");
		//  //}
	//}
		public static void RegisterFont(string fontName)
		{
			if (!iTextSharp.text.FontFactory.IsRegistered(fontName))
			{
				foreach (string name in FontKey.GetValueNames())
				{
					if (name.StartsWith(fontName))
					{
						string fontFile = (string)FontKey.GetValue(name);
						iTextSharp.text.FontFactory.Register(fontFile.Contains("\\") ? fontFile : FontFolder + "\\" + fontFile);
					}
				}
			}
		}
		private static RegistryKey _FontKey = Registry.LocalMachine.OpenSubKey("Software").OpenSubKey("Microsoft").OpenSubKey("Windows NT").OpenSubKey("CurrentVersion").OpenSubKey("Fonts");
		public static RegistryKey FontKey
		{ get { return _FontKey; } }
		private static string _FontFolder = (String)Registry.CurrentUser.OpenSubKey("Software").OpenSubKey("Microsoft").OpenSubKey("Windows").OpenSubKey("CurrentVersion").OpenSubKey("Explorer").OpenSubKey("Shell Folders").GetValue("Fonts");
		public static string FontFolder
		{ get { return _FontFolder; } }
		private float ScaleY(float y)
		{
			return _VGOutput.PdfWriter.PageSize.Height - y;
		}
	}
}
