using System;
using System.Windows;
using System.Collections.Generic;
using System.Threading;
using System.Windows.Xps.Packaging;
using System.Printing;
using System.Windows.Input;
using System.IO;
using GhostNET;

namespace ghostnet_wpf_example
{
	public partial class MainWindow
	{
		Print m_printcontrol = null;
		private xpsprint m_xpsprint = null;

		public void PrintDiagPrint(object PrintDiag)
		{
			bool print_all = false;
			int first_page = 1;
			int last_page = 1;

			if (!m_printcontrol.RangeOK())
				return;

			/* Create only the page range that is needed. */
			switch (m_printcontrol.m_pages_setting)
			{
				case PrintPages_t.RANGE:
					first_page = m_printcontrol.m_from;
					last_page = m_printcontrol.m_to;
					break;
				case PrintPages_t.CURRENT:
					first_page = m_currpage + 1;
					last_page = m_currpage + 1;
					break;
				case PrintPages_t.ALL:
					print_all = true;
					first_page = 1;
					last_page = m_numpages + 1;
					break;
			}

			/* If file is already xps then gs need not do this */
			if (!(m_document_type == doc_t.XPS))
			{
				xaml_DistillProgress.Value = 0;

				if (m_ghostscript.CreateXPS(m_currfile, Constants.DEFAULT_GS_RES,
						last_page - first_page + 1, m_printcontrol, first_page, last_page) == gsStatus.GS_BUSY)
				{
					ShowMessage(NotifyType_t.MESS_STATUS, "GS currently busy");
					return;
				}
				else
				{
					xaml_CancelDistill.Visibility = System.Windows.Visibility.Collapsed;
					xaml_DistillName.Text = "Convert to XPS";
					xaml_DistillName.FontWeight = FontWeights.Bold;
					xaml_DistillGrid.Visibility = System.Windows.Visibility.Visible;
				}
			}
			else
				PrintXPS(m_currfile, print_all, first_page, last_page, false);
		}

		private void PrintCommand(object sender, ExecutedRoutedEventArgs e)
		{
			Print(sender, e);
		}

		/* Printing is achieved using xpswrite device in ghostscript and
		 * pushing that file through the XPS print queue */
		private void Print(object sender, ExecutedRoutedEventArgs e)
		{
			if (!m_file_open)
				return;

			if (m_printcontrol == null)
			{
				m_printcontrol = new Print(this, m_numpages);
				m_printcontrol.Activate();
				m_printcontrol.Show();  /* Makes it modal */
			}
			else
				m_printcontrol.Show();
			return;
		}

		/* Do the actual printing on a different thread. This is an STA
		   thread due to the UI like commands that the XPS document
		   processing performs.  */
		private void PrintXPS(String file, bool print_all, int from, int to,
							bool istempfile)
		{
			Thread PrintThread = new Thread(MainWindow.PrintWork);
			PrintThread.SetApartmentState(ApartmentState.STA);

			var arguments = new List<object>();
			arguments.Add(file);
			arguments.Add(print_all);
			arguments.Add(from);
			arguments.Add(to);
			arguments.Add(m_printcontrol.m_selectedPrinter.FullName);
			arguments.Add(m_printcontrol);
			arguments.Add(istempfile);

			m_xpsprint = new xpsprint();
			m_xpsprint.PrintUpdate += PrintProgress;
			arguments.Add(m_xpsprint);

			xaml_PrintGrid.Visibility = System.Windows.Visibility.Visible;
			xaml_PrintProgress.Value = 0;
			PrintThread.Start(arguments);
		}

		/* The thread that is actually doing the print work */
		public static void PrintWork(object data)
		{
			List<object> genericlist = data as List<object>;
			String file = (String)genericlist[0];
			bool print_all = (bool)genericlist[1];
			int from = (int)genericlist[2];
			int to = (int)genericlist[3];
			String printer_name = (String)genericlist[4];
			Print printcontrol = (Print)genericlist[5];
			bool istempfile = (bool)genericlist[6];
			xpsprint xps_print = (xpsprint)genericlist[7];
			String filename = "";

			if (istempfile == true)
				filename = file;

			/* We have to get our own copy of the print queue for the thread */
			LocalPrintServer m_printServer = new LocalPrintServer();
			PrintQueue m_selectedPrinter = m_printServer.GetPrintQueue(printer_name);

			XpsDocument xpsDocument = new XpsDocument(file, FileAccess.Read);
			xps_print.Print(m_selectedPrinter, xpsDocument, printcontrol, print_all,
							from, to, filename, istempfile);

			/* Once we are done, go ahead and delete the file */
			if (istempfile == true)
				xpsDocument.Close();
			xps_print.Done();
		}

		private void PrintProgress(object printHelper, gsPrintEventArgs Information)
		{
			switch (Information.Status)
			{
				case PrintStatus_t.PRINT_ERROR:
					System.Windows.Application.Current.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(() =>
					{
						ShowMessage(NotifyType_t.MESS_ERROR, "Printer Driver Error");
						xaml_PrintGrid.Visibility = System.Windows.Visibility.Collapsed;
					}));
					break;
				case PrintStatus_t.PRINT_CANCELLED:
				case PrintStatus_t.PRINT_READY:
					System.Windows.Application.Current.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(() =>
					{
						xaml_PrintGrid.Visibility = System.Windows.Visibility.Collapsed;
					}));
					break;
				case PrintStatus_t.PRINT_DONE:
					System.Windows.Application.Current.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(() =>
					{
						xaml_PrintGrid.Visibility = System.Windows.Visibility.Collapsed;
						DeleteTempFile(Information.FileName);
					}));
					break;
				case PrintStatus_t.PRINT_BUSY:
					System.Windows.Application.Current.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(() =>
					{
						xaml_PrintProgress.Value = 100.0 * (double)(Information.Page - Information.PageStart) / (double)Information.NumPages;
						if (Information.Page == Information.NumPages)
						{
							xaml_PrintGrid.Visibility = System.Windows.Visibility.Collapsed;
						}
					}));
					break;
			}
		}
	}
}