using System;
using System.Collections.Generic;
using System.Drawing.Drawing2D;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Drawing.Imaging;
using CatalogVbLib;

namespace CatalogLib
{
	public class ImageCreator
	{

		#region Variabili

		private SinglePicData _singlePicData;
		private PicSettings _picSettings;

		private Rotazione _rotation;

		//private bool FotoRuotaADestra = false;

		//private bool FotoRuotaASinistra = false;
		private string TempMinText = "";
		//Private crFont1 As Font

		private string _NomeFileChild;
		private DirectoryInfo _SourceDir;
		private DirectoryInfo _DestDirStart;

		private DirectoryInfo _DestDir;

		private FileInfo _workFile;
		private string testoFirma;
		private string testoFirmaV;
		private int alphaScelta;
		private int _dimensioneStandard;
		private int _dimensioneStandardMiniatura;
		private DateTime dataFoto;
		private DateTime dataPartenzaI;
		private string testoOrario;
		private string testoFirmaPiccola;
		private Size thumbSizeSmall;
		private Size thumbSizeBig;
		private string nomeFileSmall;
		private string nomeFileBig;

		private string nomeFileBig2;
		private float yPosFromBottom;
		private float yPosFromBottom1;
		private float yPosFromBottom2;
		private float yPosFromBottom3;
		private float yPosFromBottom4;

		public string NomeFileChild
		{
			get { return _NomeFileChild; }
			set { _NomeFileChild = value; }
		}

		public DirectoryInfo DestDirStart
		{
			get { return _DestDirStart; }
			set { _DestDirStart = value; }
		}

		public DirectoryInfo SourceDir
		{
			get { return _SourceDir; }
			set { _SourceDir = value; }
		}

		public DirectoryInfo DestDir
		{
			get { return _DestDir; }
			set { _DestDir = value; }
		}

		public FileInfo WorkFile
		{
			get { return _workFile; }
			set { _workFile = value; }
		}

		#endregion

		//public ImageCreator(string nomeFileChild, DirectoryInfo sourceDir, DirectoryInfo destDir, DirectoryInfo destDirStart)
		//{
		//    this.NomeFileChild = nomeFileChild;
		//    SourceDir = sourceDir;
		//    DestDir = destDir;
		//    DestDirStart = destDirStart;
		//    WorkFile = new FileInfo(nomeFileChild);
		//}

		//public ImageCreator(string nomeFileChild, DirectoryInfo sourceDir, DirectoryInfo destDir)
		//{
		//    NomeFileChild = nomeFileChild;
		//    DestDir = destDir;
		//}

		//public ImageCreator(FileInfo file, DirectoryInfo destination)
		//{
		//    WorkFile = file;
		//    DestDir = destination;
		//}

		public ImageCreator(SinglePicData picData, PicSettings picSettings)
		{
			
		}

		/// <summary>
		/// Elabora l'immagine
		/// </summary>
		/// <param name="info">Non ne ho idea. ToDo: capire a che serve</param>
		public void CreaImmagineThread(string info)
		{

			//CatalogLib.PicSettings ps = new CatalogLib.PicSettings();

			PreparaVariabili();

			// Workfile deve essere impostato esternamente. ToDo: passarlo come parametro così da potere riutilizzare la classe senza eliminarla e ricrearla
			Image g = Image.FromFile(WorkFile.FullName);

			ImpostaTestoExtra(g);

			// Rotazione immagine in base ai dati EXIF
			Rotation(ref g);

			// Impostazione del formato
			// todo: mettere una selezione più specifica invece di assumere jpg
			ImageFormat currentFormat = g.RawFormat;
			if (_picSettings.UsaForzaJpg)
			{
				currentFormat = ImageFormat.Jpeg;
			}

			PrepareThumbnailSize(g);

			// big image resolution
			var imgOutputBig = new Bitmap(g, thumbSizeBig.Width, thumbSizeBig.Height);
			imgOutputBig.SetResolution(g.HorizontalResolution, g.VerticalResolution);


			if (_picSettings.CreaMiniature)
			{

				CreaMiniature(g, imgOutputBig, currentFormat);
			}

			




		}


		private void Rotation(ref System.Drawing.Image g)
		{
			//FotoRuotaADestra = false;
			//FotoRuotaASinistra = false;
			_rotation = Rotazione.Normale;

			if (_picSettings.GeneraleRotazioneAutomatica)
			{
				// ci sono dati exif
				if (g.PropertyIdList.Length > 0)
				{
					ExifReader DatiExif = new ExifReader((Bitmap)g);

					switch (DatiExif.Orientation)
					{
						case ExifReader.Orientations.BottomLeft:

							break;
						case ExifReader.Orientations.BottomRight:

							break;
						case ExifReader.Orientations.LeftTop:

							break;
						case ExifReader.Orientations.LftBottom:
							//FotoRuotaASinistra = true;
							_rotation = Rotazione.Sinistra;
							break;
						case ExifReader.Orientations.RightBottom:

							break;
						case ExifReader.Orientations.RightTop:

							break;
						case ExifReader.Orientations.TopLeft:

							break;
						case ExifReader.Orientations.TopRight:

							break;
					}
				}
			}

			if (_rotation == Rotazione.Sinistra)
			{
				g.RotateFlip(RotateFlipType.Rotate270FlipNone);
			}else
			if (_rotation == Rotazione.Destra)
			{
				g.RotateFlip(RotateFlipType.Rotate90FlipNone);
			}
			// todo: capire quando va ruotato a destra
		}

		/// <summary>
		/// Aggiunge orario e tempo gara
		/// </summary>
		/// <param name="g"></param>
		private void ImpostaTestoExtra(Image g)
		{
			if (_picSettings.UsaOrarioTestoApplicare ||
				_picSettings.UsaTempoGaraTestoApplicare ||
				_picSettings.UsaOrarioMiniatura ||
				_picSettings.TestoMin ||
				_picSettings.AggTempoGaraMin ||
				_picSettings.AggNumTempMin)
			{
				if (g.PropertyIdList.Length > 0) //ci sono dati exif
				{
					var datiExix = new ExifReader((Bitmap)g);
					dataFoto = datiExix.DateTimeOriginal;
					testoFirma = _picSettings.TestoFirmaStart;
					testoFirmaV = _picSettings.TestoFirmaStartV;

					if (dataFoto.Year != 1)
					{
						testoFirmaPiccola = dataFoto.ToShortDateString();
						if (_picSettings.UsaOrarioTestoApplicare)
						{
							testoFirma = $"{testoFirma} {dataFoto.ToShortDateString()} {dataFoto.ToLongDateString()}";
							testoFirmaV = $"{testoFirmaV} {dataFoto.ToShortDateString()} {dataFoto.ToLongDateString()}";
							//testoFirma = string.Concat(testoFirma, " ", dataFoto.ToShortDateString(), " ", dataFoto.ToLongDateString());
							//testoFirmaV = string.Concat(testoFirmaV, " ", dataFoto.ToShortDateString(), " ", dataFoto.ToLongDateString());

						}
						if (_picSettings.UsaTempoGaraTestoApplicare)
						{
							//TimeSpan orario = dataPartenzaI - dataFoto;

							string orarioString = (dataPartenzaI - dataFoto).ToString(@"hh\:mm\:ss");

							testoFirma = $"{testoFirma} {testoOrario} {orarioString}";
							testoFirmaV = $"{testoFirmaV} {testoOrario} {orarioString}";

							//testoFirma = string.Concat(testoFirma, " ", testoOrario, orario.ToString(@"hh\:mm\:ss"));
							//testoFirmaV = string.Concat(testoFirmaV, " ", testoOrario, orario.ToString(@"hh\:mm\:ss"));
						}
					}
				}
			}
			else
			{
				testoFirma = _picSettings.TestoFirmaStart;
				testoFirmaV = _picSettings.TestoFirmaStartV;
			}
		}

		/// <summary>
		/// Preparazione delle variabili a valori di default e caricamento da impostazioni
		/// </summary>
		private void PreparaVariabili()
		{
			alphaScelta = (int)(255 * (100 - _picSettings.Trasparenza) / 100);
			testoFirma = string.Empty;
			testoFirmaV = string.Empty;
			dataPartenzaI = _picSettings.DataPartenza;
			testoOrario = _picSettings.TestoOrario;
			if (testoOrario.Length > 0)
			{
				testoOrario += " ";
			}
			testoFirmaPiccola = string.Empty;
			thumbSizeSmall = new Size();
			thumbSizeBig = new Size();
			nomeFileSmall = string.Empty;
			nomeFileBig2 = string.Empty;
			nomeFileBig = string.Empty;
			_dimensioneStandard = _picSettings.DimStandard;
			_dimensioneStandardMiniatura = _picSettings.DimStandardMiniatura;

			nomeFileSmall = _picSettings.Suffisso + WorkFile.Name;
			nomeFileBig = WorkFile.Name;
		}

		private void PrepareThumbnailSize(Image g)
		{
			if (g.Width > g.Height)
			{
				thumbSizeSmall = NewthumbSize(g.Width, g.Height, CatalogVbLib.PicSettings.LarghezzaSmall, "Larghezza");
				//Size sizeOrig = new Size(g.Width, g.Height);
				//thumbSizeBig = sizeOrig;
				
				thumbSizeBig = new Size(g.Width, g.Height);
			}
			else
			{
				thumbSizeSmall = NewthumbSize(g.Width, g.Height, CatalogVbLib.PicSettings.AltezzaSmall, "Altezza");
				
				thumbSizeBig = new Size(g.Width, g.Height);
			}
		}

		private void CreaMiniature(Image g, Bitmap imgOutputBig, ImageFormat thisFormat)
		{
//            CatalogLib.PicSettings ps = new PicSettings();

			if (_picSettings.TestoMin)
			{
				testoFirmaPiccola = nomeFileBig;
			}
			else if (_picSettings.AggNumTempMin)
			{
				testoFirmaPiccola = nomeFileBig + " ";
			}

			Font crFont1;
			Font crFont2;
			SizeF crSize1 = new SizeF();
			SizeF crSize2 = new SizeF();

			if (_picSettings.CreaMiniature)
			{
				if (!_picSettings.AggiungiScritteMiniature)
				{
					if (string.Equals(_picSettings.DirectorySorgente, _picSettings.DirectoryDestinazione, StringComparison.CurrentCultureIgnoreCase))
					{
						nomeFileSmall = nomeFileSmall.Substring(0, nomeFileSmall.Length - 4) + _picSettings.Codice +
										nomeFileSmall.Substring(nomeFileSmall.Length - 4);
					}

					if (_picSettings.UsaOrarioMiniatura ||
						_picSettings.TestoMin ||
						_picSettings.AggTempoGaraMin ||
						_picSettings.AggNumTempMin)
					{
						if (!string.IsNullOrWhiteSpace(testoFirmaPiccola))
						{
							Bitmap imgOutputSmall = (Bitmap)imgOutputBig.Clone();

							Graphics grPhoto1 = Graphics.FromImage(imgOutputSmall);
							grPhoto1.SmoothingMode = SmoothingMode.HighSpeed; //Todo: permettere di cambiare questo parametro

							int larghezzaStandard1;

							_dimensioneStandardMiniatura = 50;
							bool grassetto = _picSettings.Grassetto;
							crFont1 = new Font(_picSettings.IlFont, _dimensioneStandardMiniatura, grassetto ? FontStyle.Bold : FontStyle.Regular);
							crFont2 = new Font(_picSettings.IlFont, _dimensioneStandard, grassetto ? FontStyle.Bold : FontStyle.Regular);

							crSize1 = grPhoto1.MeasureString(testoFirmaPiccola, crFont1);
							crSize2 = grPhoto1.MeasureString(testoFirma, crFont1);

							larghezzaStandard1 = (int)crSize1.Width;

							if (crSize1.Width > g.Width)
							{
								int conta = _dimensioneStandardMiniatura;
								do
								{
									if (conta > 20)
									{
										conta -= 5;
									}
									else
									{
										conta -= 1;
									}

									crFont1 = new Font(_picSettings.IlFont, conta, grassetto ? FontStyle.Bold : FontStyle.Regular);
									crSize1 = grPhoto1.MeasureString(testoFirmaPiccola, crFont1);

									if (crSize1.Width < g.Width)
									{
										larghezzaStandard1 = (int)crSize1.Width;
										break;
									}

								} while (conta > 5);
								_dimensioneStandardMiniatura = conta;

							}

							switch (_picSettings.TextPosition.ToString().ToUpper())
							{
								case "ALTO":
									yPosFromBottom1 = _picSettings.Margine;
									yPosFromBottom4 = _picSettings.MargVert;
									break;

								case "BASSO":
									yPosFromBottom1 =
										(float)
											(g.Height - crSize1.Height - (g.Height * CatalogVbLib.PicSettings.Margine / 100));
									yPosFromBottom4 = (float)(g.Height - crSize1.Height - (g.Height * CatalogVbLib.PicSettings.MargVert / 100));
									break;
							}


							float xCenterOfImg1 = Single.NaN;

							StringFormat strFormat1 = new StringFormat();

							switch (_picSettings.Allineamento.ToUpper())
							{
								case "SINISTRA":
									xCenterOfImg1 = CatalogVbLib.PicSettings.Margine + (larghezzaStandard1 / 2);
									if ((larghezzaStandard1 / 2) > (g.Width / 2) - CatalogVbLib.PicSettings.Margine)
									{
										xCenterOfImg1 = g.Width / 2;
									}
									break;

								case "CENTRO":
									xCenterOfImg1 = (g.Width / 2);
									break;

								case "DESTRA":
									xCenterOfImg1 = (g.Width - CatalogVbLib.PicSettings.Margine - (larghezzaStandard1 / 2));
									if ((larghezzaStandard1 / 2) > (g.Width / 2) - CatalogVbLib.PicSettings.Margine)
									{
										xCenterOfImg1 = g.Width / 2;
									}
									break;

							}

							strFormat1.Alignment = StringAlignment.Center;

							SolidBrush semiTransBrush21 = new SolidBrush(Color.FromArgb(alphaScelta, 0, 0, 0));
							SolidBrush semiTransBrush1 = new SolidBrush(Color.FromArgb(alphaScelta, CatalogVbLib.PicSettings.fontColoreRGB));

							_dimensioneStandardMiniatura = CatalogVbLib.PicSettings.DimMin;

							if (_picSettings.Grassetto)
							{
								crFont1 = new Font(_picSettings.IlFont, _dimensioneStandardMiniatura, FontStyle.Bold);
							}
							else
							{
								crFont1 = new Font(_picSettings.IlFont, _dimensioneStandardMiniatura);
							}

							if (_picSettings.TestoMin)
							{
								grPhoto1.DrawString(nomeFileBig, crFont1, semiTransBrush21, new PointF(xCenterOfImg1 + 1, yPosFromBottom1 + 1), strFormat1);
								grPhoto1.DrawString(nomeFileBig, crFont1, semiTransBrush1, new PointF(xCenterOfImg1, yPosFromBottom1), strFormat1);
							}
							else if (_picSettings.AggTempoGaraMin & _picSettings.UsaTempoGaraTestoApplicare)
							{
								//TimeSpan orario = (dataPartenzaI - dataFoto) * 10000000; //todo
								TimeSpan orario = dataPartenzaI - dataFoto; //todo controllare se torna la roba giusta

								string tempStr = "";



								tempStr += Environment.NewLine + testoOrario + orario.Hours.ToString("00") + ":" +
										   orario.Minutes.ToString("00") + ":" + orario.Seconds.ToString("00"); //todo: usare una stringa formato per sta boiata

								grPhoto1.DrawString(tempStr, crFont1, semiTransBrush21, new PointF(xCenterOfImg1 + 1, yPosFromBottom1 + 1));
								grPhoto1.DrawString(tempStr, crFont1, semiTransBrush1, new PointF(xCenterOfImg1, yPosFromBottom1), strFormat1);
							}
							else if (_picSettings.AggNumTempMin) //todo semplificare la logica di sti eif
							{
								TimeSpan orario = dataPartenzaI - dataFoto; //todo controllare se torna la roba giusta
								string tempStr = "";
								tempStr += nomeFileBig + Environment.NewLine + testoOrario + orario.Hours.ToString("00") + ":" +
										   orario.Minutes.ToString("00") + ":" + orario.Seconds.ToString("00"); //todo: usare una stringa formato per sta boiata

								grPhoto1.DrawString(tempStr, crFont1, semiTransBrush21, new PointF(xCenterOfImg1 + 1, yPosFromBottom1 + 1));
								grPhoto1.DrawString(tempStr, crFont1, semiTransBrush1, new PointF(xCenterOfImg1, yPosFromBottom1), strFormat1);
							}
							else
							{
								grPhoto1.DrawString(testoFirmaPiccola, crFont1, semiTransBrush21, new PointF(xCenterOfImg1 + 1, yPosFromBottom1 + 1), strFormat1);
								grPhoto1.DrawString(testoFirmaPiccola, crFont1, semiTransBrush1, new PointF(xCenterOfImg1, yPosFromBottom1), strFormat1);
							}


							//Salva miniatura
							
							imgOutputSmall.Save(Path.Combine(DestDir.FullName, "Temp_" + nomeFileSmall), thisFormat);
							float width = 0;
							float height = 0;
							//float scale = Math.Min(width/imgOutputSmall.Width, height/imgOutputSmall.Height);
							using (var bmp = new Bitmap(thumbSizeSmall.Width, thumbSizeSmall.Height))
							{
								using (var graph = Graphics.FromImage(bmp))
								{
									// uncomment for higher quality output
									//graph.InterpolationMode = InterpolationMode.High;
									//graph.CompositingQuality = CompositingQuality.HighQuality;
									//graph.SmoothingMode = SmoothingMode.AntiAlias;

									graph.DrawImage(imgOutputSmall, new Rectangle(0, 0, (int)width, (int)height));

									bmp.Save(Path.Combine(DestDir.FullName, nomeFileSmall), thisFormat);
								}
							}
							//var bmp = new Bitmap(thumbSizeSmall.Width, thumbSizeSmall.Height);
							//var graph = Graphics.FromImage(bmp);



//                             10 down vote accepted
	

//Target parameters:

//float width = 1024;
//float height = 768;
//var brush = new SolidBrush(Color.Black);

//Your original file:

//var image = new Bitmap(file);

//Target sizing (scale factor):

//float scale = Math.Min(width / image.Width, height / image.Height);

//The resize including brushing canvas first:

//var bmp = new Bitmap((int)width, (int)height);
//var graph = Graphics.FromImage(bmp);

//// uncomment for higher quality output
////graph.InterpolationMode = InterpolationMode.High;
////graph.CompositingQuality = CompositingQuality.HighQuality;
////graph.SmoothingMode = SmoothingMode.AntiAlias;

//var scaleWidth = (int)(image.Width * scale);
//var scaleHeight = (int)(image.Height * scale);

//graph.FillRectangle(brush, new RectangleF(0, 0, width, height));
//graph.DrawImage(image, new Rectangle(((int)width - scaleWidth)/2, ((int)height - scaleHeight)/2, scaleWidth, scaleHeight));



							//imgOutputSmall.Save(Path.Combine(DestDir.FullName, nomeFileSmall), thisFormat);


							//Image g2 = Image.FromFile(Path.Combine(DestDir.FullName, "Temp_" + nomeFileSmall));
							//Bitmap imgOutputSmall2 = new Bitmap(g2, thumbSizeSmall.Width, thumbSizeSmall.Height);
							//imgOutputSmall2.Save(Path.Combine(DestDir.FullName, nomeFileSmall), thisFormat);



						}
					}


				}
			}



		}



		/// <summary>
		/// Calculate the Size of the New image
		/// </summary>
		/// <param name="currentwidth">Larghezza</param>
		/// <param name="currentheight">Altezza</param>
		/// <param name="MaxPixel"></param>
		/// <param name="TipoSize"></param>
		/// <returns></returns>
		/// <remarks></remarks>
		private Size NewthumbSize(int currentwidth, int currentheight, int MaxPixel, string TipoSize)
		{
			// e  
			//*** Larghezza, Altezza, Auto

			double tempMultiplier = 0;

			if (TipoSize.ToUpper() == "Larghezza".ToUpper())
			{
				tempMultiplier = MaxPixel / currentwidth;
			}
			else if (TipoSize.ToUpper() == "Altezza".ToUpper())
			{
				tempMultiplier = MaxPixel / currentheight;
			}
			else
			{
				// portrait  
				if (currentheight > currentwidth)
				{
					tempMultiplier = MaxPixel / currentheight;
				}
				else
				{
					tempMultiplier = MaxPixel / currentwidth;
				}
			}

			Size NewSize = new Size(Convert.ToInt32(currentwidth * tempMultiplier), Convert.ToInt32(currentheight * tempMultiplier));

			return NewSize;
		}
	}
}
