using System;
using Telerik.Web.UI;
using Telerik.Web.UI.Editor.Export;
using Telerik.Windows.Documents.Model;
using Telerik.Windows.Documents.FormatProviders.Pdf;
using Telerik.Windows.Documents.FormatProviders.Html;
using System.Threading;
using System.Net;
using System.IO;

public class TelerikPdfExportTemplate: RadEditorExportTemplate
{
	public TelerikPdfExportTemplate (RadEditor radEditor) : base(radEditor)
	{
	}

	//no need to initialize the XmlContent
	protected override void InitializeXmlContent()
	{
	}

	protected override string GenerateOutput()
	{
		string output = "";
		var thread = new Thread(() =>
		{
			PdfFormatProvider provider = new PdfFormatProvider();
			
			RadDocument document = this.ImportDocument();
            this.ProcessDocument(document);
			
			byte [] buffer = provider.Export(document);
			output = ResponseWriteEncoding.GetString(buffer);
		});
		thread.SetApartmentState(ApartmentState.STA);
		thread.Start();
		thread.Join();
		return output;
	}
	
	private RadDocument ImportDocument()
	{
		HtmlFormatProvider provider = new HtmlFormatProvider();
		provider.ImportSettings.LoadImageFromUrl += ImportSettings_LoadImageFromUrl;

		return provider.Import(editor.Content);
	}

	void ImportSettings_LoadImageFromUrl(object sender, LoadImageEventArgs e)
	{
        //This ensures images are properly loaded from url.
		WebRequest req = WebRequest.Create(e.Url);
		WebResponse response = req.GetResponse();
		Stream imageStream = response.GetResponseStream();

		using (var memoryStream = new MemoryStream())
		{
			imageStream.CopyTo(memoryStream);
			string extension = Path.GetExtension(e.Url);
			e.ImageElement.Init(memoryStream, extension);
			e.ImageElement.Tag = e.Url;
			e.Handled = true;
		}
	}

	private void ProcessDocument(RadDocument document)
	{
		document.LayoutMode = DocumentLayoutMode.Paged;

        //This reduces the space added by RadDocument's model before and after table elements.
		RadDocumentEditor documentEditor = new RadDocumentEditor(document);
		var tables = documentEditor.Document.EnumerateChildrenOfType<Table>();

		foreach (var table in tables)
		{
			Paragraph previousParagraph = table.PreviousSibling as Paragraph;
			if (previousParagraph != null && previousParagraph.IsEmpty)
			{
				documentEditor.Document.CaretPosition.MoveToEndOfDocumentElement(previousParagraph);
				documentEditor.ChangeParagraphSpacingAfter(0);
				documentEditor.ChangeFontSize(2);
			}

			Paragraph nextParagraph = table.NextSibling as Paragraph;
			if (nextParagraph != null && nextParagraph.IsEmpty)
			{
				documentEditor.Document.CaretPosition.MoveToEndOfDocumentElement(nextParagraph);
				documentEditor.ChangeParagraphSpacingAfter(0);
				documentEditor.ChangeFontSize(2);
			}
		}
	}	

	protected override string ContentType
	{
		get { return "application/pdf"; }
	}

	protected override string FileExtension
	{
		get { return ".pdf"; }
	}

	protected override ExportType ExportType
	{
		get { return ExportType.Pdf; }
	}
}
