using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Xps;
using System.Windows.Xps.Packaging;
using Microsoft.Win32;
using System.IO;
using System.IO.Packaging;
using System.Printing;
using System.Windows.Markup;
using System.Windows.Controls.Primitives;

namespace OPlanner {

	public partial class ExportPrintCourses : Window {

		private OCurrentInfo info;
		private PrintDialog printDialog;

		public ExportPrintCourses() {
			InitializeComponent();
			dpiBox.Text = "96";
			qualityBox.Text = "80";
		}

		public void SetPrintDialog(PrintDialog newDialog) {
			printDialog = newDialog;
			UpdatePrintInfo();
		}

		private void UpdatePrintInfo() {
			printerLabel.Content = "Printer: " + printDialog.PrintQueue.FullName;
		}

		public void SetInfo(OCurrentInfo newInfo) {
			info = newInfo;
			UpdateCourses();
		}

		private bool ValidateExport(bool showErrors) {
			ErrorManager errorManager = new ErrorManager();
			double num;
			if (dpiBox.Text == "") {
				errorManager.AddError("Dpi is required");
			} else {
				if (!double.TryParse(dpiBox.Text, out num)) {
					errorManager.AddError("Dpi must be a number");
				} else {
					if (num <= 0 || num > 1200) {
						errorManager.AddError("Dpi must be between 1 and 1200");
					}
				}
			}
			if (jpegButton.IsChecked == true) {
				int val;
				if (qualityBox.Text == "") {
					errorManager.AddError("Quality is required");
				} else {
					if (!int.TryParse(qualityBox.Text, out val)) {
						errorManager.AddError("Quality must be an integer");
					} else {
						if (val <= 0 || val > 100) {
							errorManager.AddError("Quality must be between 1 and 100");
						}
					}
				}
			}
			if (showErrors) {
				errorManager.ShowErrors(this);
			}
			return !errorManager.HasErrors;
		}

		private void exportButton_Click(object sender, RoutedEventArgs e) {
			if (coursesBox.SelectedItems.Count == 0) {
				ErrorManager errorManager = new ErrorManager();
				errorManager.AddError("Please select a course");
				errorManager.ShowErrors(this);
				return;
			}
			if (!ValidateExport(true)) {
				return;
			}
			for (int i = 0; i < coursesBox.SelectedItems.Count; i++) {
				double borderWidth = 0;
				object objectData = ((CustomListBoxItem)coursesBox.SelectedItems[i]).ObjectData;
				OCurrentInfo newInfo = new OCurrentInfo();
                newInfo.DescriptionManager = info.DescriptionManager;
				OCanvas oCanvas = new OCanvas();
				oCanvas.SetInfo(newInfo);
				newInfo.LoadData(info.Data.Clone());
				if (objectData is OPlannerData || objectData == null) {
					newInfo.SelectedCourse = null;
				} else {
					newInfo.SelectedCourse = newInfo.Data.GetCourseByName(((Course)objectData).Name);
				}
				if (objectData == null) {
					newInfo.CourseViewType = CourseViewType.HideAll;
				} else {
					newInfo.CourseViewType = CourseViewType.Preview;
				}
				newInfo.InvokeCourseSelected(this);
				oCanvas.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
				oCanvas.Arrange(new Rect(new Point(borderWidth, borderWidth), oCanvas.DesiredSize));
				Size size = oCanvas.DesiredSize;
				SaveFileDialog dlg = new SaveFileDialog();
				dlg.FileName = Convert.ToString(((CustomListBoxItem)coursesBox.SelectedItems[i]).Content).Replace(" ", "");
				if (jpegButton.IsChecked == true) {
					dlg.DefaultExt = ".jpg";
					dlg.FileName += ".jpg";
					dlg.Filter = "Jpeg|*.jpg";
				} else if (pngButton.IsChecked == true) {
					dlg.DefaultExt = ".png";
					dlg.FileName += ".png";
					dlg.Filter = "Png|*.png";
				}
				if (dlg.ShowDialog(this) != true) {
					continue;
				}
				double dpi = double.Parse(dpiBox.Text);
				int quality = int.Parse(qualityBox.Text);
				RenderTargetBitmap bmp = new RenderTargetBitmap((int)(Math.Ceiling((size.Width + borderWidth * 2)*dpi/96.0)), (int)(Math.Ceiling((size.Height + borderWidth * 2)*dpi/96.0)), dpi, dpi, PixelFormats.Pbgra32);
				BitmapEncoder encoder;
				if (jpegButton.IsChecked == true) {
					encoder = new JpegBitmapEncoder();
					((JpegBitmapEncoder)encoder).QualityLevel = quality;
				} else if (pngButton.IsChecked == true) {
					encoder = new PngBitmapEncoder();
				} else {
					continue;
				}
				Rectangle rect = new Rectangle();
				rect.Width = bmp.Width;
				rect.Height = bmp.Height;
				rect.Fill = Brushes.White;
				rect.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
				rect.Arrange(new Rect(new Point(0, 0), rect.DesiredSize));
				bmp.Render(rect);
				bmp.Render(oCanvas);
				encoder.Frames.Add(BitmapFrame.Create(bmp));
				string fileName = dlg.FileName;
				FileStream fs = new FileStream(fileName, FileMode.Create);
				encoder.Save(fs);
				fs.Close();
			}
		}

		private void UpdateCourses() {
			coursesBox.Items.Clear();
			if (info == null) {
				return;
			}
			if (info.Data == null) {
				return;
			}
			coursesBox.Items.Add(new CustomListBoxItem("Blank Map", null));
			coursesBox.Items.Add(new CustomListBoxItem("All Controls", info.Data));
			List<Course> tempList = new List<Course>(info.Data.Courses);
			tempList.Sort(CompareCourses);
			for (int i = 0; i < tempList.Count; i++) {
				CustomListBoxItem item = new CustomListBoxItem(tempList[i].Name, tempList[i]);
				coursesBox.Items.Add(item);
			}
		}

		private static int CompareCourses(Course x, Course y) {
			return x.Name.CompareTo(y.Name);
		}

		private void previewButton_Click(object sender, RoutedEventArgs e) {
			if (coursesBox.SelectedItems.Count == 0) {
				ErrorManager errorManager = new ErrorManager();
				errorManager.AddError("Please select a course");
				errorManager.ShowErrors(this);
				return;
			}
			FixedDocument fixedDoc = GetFixedDocument();
			if (fixedDoc == null) {
				return;
			}
			PrintPreview wnd = new PrintPreview();
			wnd.Owner = this;
			wnd.SetPrintDialog(printDialog);
			wnd.SetFixedDoc(fixedDoc);
			wnd.SetPrintName("OPlanner Courses");
			wnd.ShowDialog();
		}

		private FixedDocument GetFixedDocument(){
			PrintCapabilities capabilities = printDialog.PrintQueue.GetPrintCapabilities(printDialog.PrintTicket);
			Size pageSize = new Size(printDialog.PrintableAreaWidth, printDialog.PrintableAreaHeight);
			Size visibleSize = new Size(capabilities.PageImageableArea.ExtentWidth, capabilities.PageImageableArea.ExtentHeight);
			FixedDocument fixedDoc = new FixedDocument();
			for (int i = 0; i < coursesBox.SelectedItems.Count; i++) {
				OCurrentInfo newInfo = new OCurrentInfo();
				newInfo.DescriptionManager = info.DescriptionManager;
				OCanvas oCanvas = new OCanvas();
				oCanvas.SetInfo(newInfo);
				newInfo.LoadData(info.Data.Clone());
				object objectData = ((CustomListBoxItem)coursesBox.SelectedItems[i]).ObjectData;
				if (objectData is OPlannerData || objectData == null) {
					newInfo.SelectedCourse = null;
				} else {
					newInfo.SelectedCourse = newInfo.Data.GetCourseByName(((Course)objectData).Name);
				}
				if (objectData == null) {
					newInfo.CourseViewType = CourseViewType.HideAll;
				} else {
					newInfo.CourseViewType = CourseViewType.Preview;
				}
				newInfo.InvokeCourseSelected(this);
				oCanvas.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
				oCanvas.Arrange(new Rect(new Point(0, 0), oCanvas.DesiredSize));
				Size size = oCanvas.DesiredSize;
				PageContent pageContent = new PageContent();
				FixedPage page = new FixedPage();
				((IAddChild)pageContent).AddChild(page);
				fixedDoc.Pages.Add(pageContent);
				page.Width = pageSize.Width;
				page.Height = pageSize.Height;
				Canvas canvas = new Canvas();
				FixedPage.SetLeft(canvas, capabilities.PageImageableArea.OriginWidth);
				FixedPage.SetTop(canvas, capabilities.PageImageableArea.OriginHeight);
				canvas.Width = visibleSize.Width;
				canvas.Height = visibleSize.Height;
				canvas.ClipToBounds = true;
				Canvas.SetLeft(oCanvas, -info.Data.CoursesPrintXOffset + visibleSize.Width / 2 - size.Width / 2);
				Canvas.SetTop(oCanvas, -info.Data.CoursesPrintYOffset + visibleSize.Height / 2 - size.Height / 2);
				canvas.Children.Add(oCanvas);
				page.Children.Add(canvas);
			}
			return fixedDoc;
		}

		private void printerButton_Click(object sender, RoutedEventArgs e) {
			PageMediaSizeName? currentPageMediaSize = printDialog.PrintTicket.PageMediaSize.PageMediaSizeName;
			PageOrientation? currentPageOrientation = printDialog.PrintTicket.PageOrientation;
			printDialog.ShowDialog();
			if (printDialog.PrintTicket.PageMediaSize.PageMediaSizeName != currentPageMediaSize || printDialog.PrintTicket.PageOrientation != currentPageOrientation) {
				info.InvokeDataChanging(this, "Change Print Courses Settings");
				if (printDialog.PrintTicket.PageMediaSize.PageMediaSizeName == printDialog.PrintQueue.DefaultPrintTicket.PageMediaSize.PageMediaSizeName) {
					info.Data.CoursesPageMediaSize = null;
				} else {
					info.Data.CoursesPageMediaSize = printDialog.PrintTicket.PageMediaSize.PageMediaSizeName;
				}
				if (printDialog.PrintTicket.PageOrientation == printDialog.PrintQueue.DefaultPrintTicket.PageOrientation) {
					info.Data.CoursesPageOrientation = null;
				} else {
					info.Data.CoursesPageOrientation = printDialog.PrintTicket.PageOrientation;
				}
				info.InvokeDataChanged(this, "Change Print Courses Settings");
			}
			UpdatePrintInfo();
		}

		private void setPrintAreaButton_Click(object sender, RoutedEventArgs e) {
			PrintAreaProperties wnd = new PrintAreaProperties();
			wnd.Owner = this;
			PrintCapabilities capabilities = printDialog.PrintQueue.GetPrintCapabilities(printDialog.PrintTicket);
			wnd.SetAreaSize(new Size(capabilities.PageImageableArea.ExtentWidth, capabilities.PageImageableArea.ExtentHeight));
			wnd.SetInfo(info);
			wnd.ShowDialog();
		}

		private void jpegButton_Checked(object sender, RoutedEventArgs e) {
			if (qualityPanel != null) {
				qualityPanel.Visibility = Visibility.Visible;
			}
		}

		private void jpegButton_Unchecked(object sender, RoutedEventArgs e) {
			if (qualityPanel != null) {
				qualityPanel.Visibility = Visibility.Collapsed;
			}
		}

	}

}
