using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Globalization;
using System.IO;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using SixLabors.ImageSharp.Metadata.Profiles.Exif;

// Imports System.Threading

namespace MaddoShared;

[SuppressMessage("Interoperability", "CA1416:Validate platform compatibility")]
public class ImageCreatorSharp(PicSettings picSettings, ILogger<ImageCreatorSharp> logger)
{
    public async Task CreaImmagineThread(ImageState imgState, Image logo)
    {
        
        try
        {
            await Task.Run(() =>
            {
                logger.LogInformation("File: {FileInfo} Dest: {DirectoryInfo}", imgState.WorkFile, imgState.DestDir);
                PreparaVariabili(imgState);
                ExtractExif(imgState);

                using var g = Image.FromFile(imgState.WorkFile.FullName);

                // Imposta testo extra
                ImpostaTestoExtra(g, imgState);

                // Ruota l'immagine in base ai dati EXIF
                Rotation(g, imgState);

                // Forza jpeg se è selezionata l'opzione
                var thisFormat = g.RawFormat;
                if (picSettings.UsaForzaJpg == true)
                    thisFormat = ImageFormat.Jpeg;

                PrepareThumbnailSize(g, imgState);

                using var imgOutputBig = new Bitmap(g, imgState.ThumbSizeBig.Width, imgState.ThumbSizeBig.Height);

                imgOutputBig.SetResolution(g.HorizontalResolution, g.VerticalResolution);

                // Crea le miniature
                CreaMiniature(g, imgState, imgOutputBig, thisFormat);

                AggiungiTesto(g, imgState, imgOutputBig);

                AggiungiLogo(imgOutputBig, imgState, logo);

                SalvaFoto(imgOutputBig, imgState, thisFormat);
            });

            // g.Dispose()

            //GC.Collect();
        }

        // _picSettings.mainForm.stepProgressBar()

        catch (Exception ex)
        {
            var e = ex.Demystify();
            logger.LogError(e, "Error in processing photo {WorkFileName}", imgState.WorkFile.Name);
        }
    }

    private void ExtractExif(ImageState imgState)
    {
        using var img = SixLabors.ImageSharp.Image.Load(imgState.WorkFile.FullName);
        imgState.Orientation = Orientations.TopLeft;

        IExifValue<ushort> rotation = null;

        var found = img.Metadata?.ExifProfile?.TryGetValue(ExifTag.Orientation, out rotation) ?? false;

        if (found )
        {
            var intOrientation = rotation.Value.ToInt32();
            imgState.Orientation = (Orientations)intOrientation;
        }

        IExifValue<string> date = null;
        var creationFound = img.Metadata?.ExifProfile?.TryGetValue(ExifTag.DateTimeOriginal, out date) ?? false;
        if (creationFound)
        {
            var succ = DateTime.TryParseExact(date.Value, "yyyy:MM:dd HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.None, out var crDate);
            if (succ)
            {
                imgState.CreationDate = crDate;
            }
            else
            {
                imgState.CreationDate = null;
            }
        }
        else
        {
            imgState.CreationDate = null;
        }
    }

    private void Rotation(System.Drawing.Image g, ImageState imgState)
    {
        imgState.FotoRuotaADestra = false;
        imgState.FotoRuotaASinistra = false;

        if (picSettings.UsaRotazioneAutomatica == true)
        {
            if (g.PropertyIdList.Length > 0)
            {
                //ExifReader DatiExif = new ExifReader((Bitmap)g);

                switch (imgState.Orientation /*DatiExif.Orientation*/)
                {
                    case Orientations.BottomLeft:
                    case Orientations.BottomRight:
                    case Orientations.LeftTop:
                    case Orientations.LftBottom:
                        imgState.FotoRuotaASinistra = true;
                        break;
                    case Orientations.RightBottom:
                    case Orientations.RightTop:
                    case Orientations.TopLeft:
                    case Orientations.TopRight:
                        break;

                }
            }
        }

        if (imgState.FotoRuotaASinistra)
            g.RotateFlip(RotateFlipType.Rotate270FlipNone);
        if (imgState.FotoRuotaADestra)
            g.RotateFlip(RotateFlipType.Rotate90FlipNone);
    }

    /// <summary>
    ///     ''' Aggiunge Orario, tempo gara e altri
    ///     ''' </summary>
    ///     ''' <param name="g">Image</param>
    ///     <param name="imgState"></param>
    ///     ''' <remarks></remarks>
    private void ImpostaTestoExtra(Image g, ImageState imgState)
    {
        if (picSettings.UsaOrarioTestoApplicare | picSettings.UsaTempoGaraTestoApplicare | picSettings.UsaOrarioMiniatura | picSettings.TestoMin | picSettings.AggTempoGaraMin | picSettings.AggNumTempMin)
        {
            if (g.PropertyIdList.Length <= 0) return;
            //ExifReader DatiExif = new ExifReader((Bitmap)g);
            imgState.DataFoto = imgState.CreationDate ?? DateTime.Now; //DatiExif.DateTimeOriginal;
            imgState.TestoFirma = picSettings.TestoFirmaStart;
            imgState.TestoFirmaV = picSettings.TestoFirmaStartV;

            if (imgState.DataFoto.Year == 1) return;
            imgState.TestoFirmaPiccola = imgState.DataFoto.ToShortTimeString();
            if (picSettings.UsaOrarioTestoApplicare == true)
            {
                imgState.TestoFirma +=
                    $" {imgState.DataFoto.ToShortDateString()} {imgState.DataFoto.ToLongTimeString()}";
                imgState.TestoFirmaV +=
                    $" {imgState.DataFoto.ToShortDateString()} {imgState.DataFoto.ToLongTimeString()}";
            }

            if (picSettings.UsaTempoGaraTestoApplicare != true) return;
            var diff = imgState.DataFoto - imgState.DataPartenzaI;
            //var diffA = diff.TotalSeconds * 10000000;
            
            // var orario = new TimeSpan(0, Math.Abs(diff.Hours), Math.Abs(diff.Minutes), (int)diffA);
            imgState.TestoFirma += $" {imgState.TestoOrario}{diff.Hours:00}:{diff.Minutes:00}:{diff.Seconds:00}";
            imgState.TestoFirmaV += $" {imgState.TestoOrario}{diff.Hours:00}:{diff.Minutes:00}:{diff.Seconds:00}";
        }
        else
        {
            imgState.TestoFirma = picSettings.TestoFirmaStart;
            imgState.TestoFirmaV = picSettings.TestoFirmaStartV;
        }
    }

    /// <summary>
    ///     ''' Prepara diverse variabili azzerandole, elaborandole e prendendole dalle impostazioni
    ///     ''' </summary>
    ///     ''' <remarks></remarks>
    private void PreparaVariabili(ImageState imgState)
    {
        imgState.AlphaScelta = System.Convert.ToInt32((255 * (100 - picSettings.Trasparenza) / (double)100));
        imgState.TestoFirma = "";
        imgState.TestoFirmaV = "";
        imgState.DataPartenzaI = picSettings.DataPartenza;
        imgState.TestoOrario = picSettings.TestoOrario;
        if (imgState.TestoOrario.Length > 0)
            imgState.TestoOrario += " ";
        imgState.TestoFirmaPiccola = "";
        imgState.ThumbSizeSmall = new Size();
        imgState.ThumbSizeBig = new Size();
        imgState.NomeFileSmall = "";
        imgState.NomeFileBig2 = "";
        imgState.NomeFileBig = "";
        imgState.DimensioneStandard = picSettings.DimStandard;
        imgState.DimensioneStandardMiniatura = picSettings.DimStandardMiniatura;
        // nomeFileSmall = Suffisso & NomeFileChild
        // nomeFileBig = NomeFileChild
        imgState.NomeFileSmall = picSettings.Suffisso + imgState.WorkFile.Name;
        imgState.NomeFileBig = imgState.WorkFile.Name;
    }

    private void PrepareThumbnailSize(Image g, ImageState  imgState)
    {
        if (g.Width > g.Height)
        {
            imgState.ThumbSizeSmall = NewthumbSize(g.Width, g.Height, picSettings.LarghezzaSmall, "Larghezza");
            var sizeOrig = new Size(g.Width, g.Height);
            imgState.ThumbSizeBig = sizeOrig;
        }
        else
        {
            imgState.ThumbSizeSmall = NewthumbSize(g.Width, g.Height, picSettings.AltezzaSmall, "Altezza");
            var sizeOrig = new Size(g.Width, g.Height);
            imgState.ThumbSizeBig = sizeOrig;
        }
    }

    private void CreaMiniature(Image g, ImageState imgState, Bitmap imgOutputBig, ImageFormat thisFormat)
    {
        if (picSettings.TestoMin)
            imgState.TestoFirmaPiccola = imgState.NomeFileBig;
        else if (picSettings.AggNumTempMin)
            imgState.TestoFirmaPiccola = imgState.NomeFileBig + " ";
        // Dim yPosFromBottom4 As Single

        Font crFont1 = null/* TODO Change to default(_) if this is not a reference type */;
        Font crFont2 = null/* TODO Change to default(_) if this is not a reference type */;
        var crSize1 = new SizeF();
        var crSize2 = new SizeF();

        if (picSettings.CreaMiniature == true)
        {
            if (picSettings.AggiungiScritteMiniature == false)
            {
                if (string.Equals(picSettings.DirectorySorgente, picSettings.DirectoryDestinazione, StringComparison.OrdinalIgnoreCase))
                    imgState.NomeFileSmall = imgState.NomeFileSmall.Substring(0, imgState.NomeFileSmall.Length - 4) + picSettings.Codice + imgState.NomeFileSmall.Substring(imgState.NomeFileSmall.Length - 4);
                if (picSettings.UsaOrarioMiniatura | picSettings.TestoMin | picSettings.AggTempoGaraMin | picSettings.AggNumTempMin)
                {
                    if (imgState.TestoFirmaPiccola.Length > 0)
                    {
                        using var imgOutputSmall = (Bitmap)imgOutputBig.Clone();
                        using var grPhoto1 = Graphics.FromImage(imgOutputSmall);
                        grPhoto1.SmoothingMode = SmoothingMode.AntiAlias;

                        // quick fix
                        imgState.DimensioneStandardMiniatura = 50;
                        if (picSettings.Grassetto == true)
                        {
                            crFont1 = new Font(picSettings.IlFont, imgState.DimensioneStandardMiniatura, FontStyle.Bold);
                            crFont2 = new Font(picSettings.IlFont, imgState.DimensioneStandard, FontStyle.Bold);
                        }
                        else
                        {
                            crFont1 = new Font(picSettings.IlFont, imgState.DimensioneStandardMiniatura);
                            crFont2 = new Font(picSettings.IlFont, imgState.DimensioneStandard);
                        }

                        crSize1 = grPhoto1.MeasureString(imgState.TestoFirmaPiccola, crFont1);
                        crSize2 = grPhoto1.MeasureString(imgState.TestoFirma, crFont1);
                        var larghezzaStandard1 = System.Convert.ToInt32(crSize1.Width);

                        if (crSize1.Width > System.Convert.ToSingle(g.Width))
                        {
                            int Conta = imgState.DimensioneStandardMiniatura;
                            do
                            {
                                if (Conta > 20)
                                    Conta -= 5;
                                else
                                    Conta -= 1;
                                if (picSettings.Grassetto == true)
                                    crFont1 = new Font(picSettings.IlFont, Conta, FontStyle.Bold);
                                else
                                    crFont1 = new Font(picSettings.IlFont, Conta);
                                crSize1 = grPhoto1.MeasureString(imgState.TestoFirmaPiccola, crFont1);
                                if (crSize1.Width < System.Convert.ToSingle(g.Width))
                                {
                                    larghezzaStandard1 = System.Convert.ToInt32(crSize1.Width);
                                    break;
                                }

                                if (Conta <= 5)
                                    break;
                            }
                            while (true);
                            imgState.DimensioneStandardMiniatura = Conta;
                        }

                        switch (picSettings.Posizione.ToUpper())
                        {
                            case "ALTO":
                            {
                                imgState.YPosFromBottom1 = (picSettings.Margine);
                                imgState.YPosFromBottom4 = (picSettings.MargVert);
                                break;
                            }

                            case "BASSO":
                            {
                                imgState.YPosFromBottom1 = System.Convert.ToSingle((g.Height - crSize1.Height - (g.Height * picSettings.Margine / (double)100)));
                                imgState.YPosFromBottom4 = System.Convert.ToSingle((g.Height - crSize1.Height - (g.Height * picSettings.MargVert / (double)100)));
                                break;
                            }
                        }

                        float xCenterOfImg1 = 0;

                        using StringFormat strFormat1 = new StringFormat();
                        switch (picSettings.Allineamento.ToUpper())
                        {
                            case "SINISTRA":
                            {
                                xCenterOfImg1 = System.Convert.ToSingle((picSettings.Margine + (larghezzaStandard1 / (double)2)));

                                if ((larghezzaStandard1 / (double)2) > (g.Width / (double)2) - picSettings.Margine)
                                    xCenterOfImg1 = System.Convert.ToSingle((g.Width / (double)2));
                                break;
                            }

                            case "CENTRO":
                            {
                                xCenterOfImg1 = System.Convert.ToSingle((g.Width / (double)2));
                                break;
                            }

                            case "DESTRA":
                            {
                                xCenterOfImg1 = System.Convert.ToSingle((g.Width - picSettings.Margine - (larghezzaStandard1 / (double)2)));

                                if ((larghezzaStandard1 / (double)2) > (g.Width / (double)2) - picSettings.Margine)
                                    xCenterOfImg1 = System.Convert.ToSingle((g.Width / (double)2));
                                break;
                            }
                        }
                        strFormat1.Alignment = StringAlignment.Center;

                        using var semiTransBrush21 = new SolidBrush(Color.FromArgb(imgState.AlphaScelta, 0, 0, 0));
                        using var semiTransBrush1 = new SolidBrush(Color.FromArgb(imgState.AlphaScelta, picSettings.FontColoreRGB));

                        // quick fix
                        imgState.DimensioneStandardMiniatura = picSettings.DimMin;

                        if (picSettings.Grassetto == true)
                            crFont1 = new Font(picSettings.IlFont, imgState.DimensioneStandardMiniatura, FontStyle.Bold);
                        else
                            crFont1 = new Font(picSettings.IlFont, imgState.DimensioneStandardMiniatura);
                        // asdgadfhdfhjgfsjgfjygfdhsdafa
                        if (picSettings.TestoMin)
                        {
                            grPhoto1.DrawString(imgState.NomeFileBig, crFont1, semiTransBrush21, new PointF(xCenterOfImg1 + 1, imgState.YPosFromBottom1 + 1), strFormat1);
                            grPhoto1.DrawString(imgState.NomeFileBig, crFont1, semiTransBrush1, new PointF(xCenterOfImg1, imgState.YPosFromBottom1), strFormat1);
                        }
                        else if (picSettings.AggTempoGaraMin & picSettings.UsaTempoGaraTestoApplicare)
                        {
                            var diff = imgState.DataPartenzaI - imgState.DataFoto;
                            var diffA = diff.TotalSeconds * 10000000;

                            var orario = new TimeSpan(0, 0, (int)diffA);/* new TimeSpan(DateTime.DateDiff(DateInterval.Second, dataPartenzaI, dataFoto) * 10000000);*/
                            string tempstr = "";


                            tempstr += Environment.NewLine + imgState.TestoOrario + orario.Hours.ToString("00") + ":" + orario.Minutes.ToString("00") + ":" + orario.Seconds.ToString("00");


                            grPhoto1.DrawString(tempstr, crFont1, semiTransBrush21, new PointF(xCenterOfImg1 + 1, imgState.YPosFromBottom1 + 1), strFormat1);
                            grPhoto1.DrawString(tempstr, crFont1, semiTransBrush1, new PointF(xCenterOfImg1, imgState.YPosFromBottom1), strFormat1);
                        }
                        else if (picSettings.AggNumTempMin)
                        {
                            var diff = imgState.DataPartenzaI - imgState.DataFoto;
                            var diffA = diff.TotalSeconds * 10000000;
                            TimeSpan Orario = new TimeSpan(0, 0, (int)diffA);
                            string tempstr = "";
                            tempstr += imgState.NomeFileBig;

                            tempstr += Environment.NewLine + imgState.TestoOrario + Orario.Hours.ToString("00") + ":" + Orario.Minutes.ToString("00") + ":" + Orario.Seconds.ToString("00");


                            grPhoto1.DrawString(tempstr, crFont1, semiTransBrush21, new PointF(xCenterOfImg1 + 1, imgState.YPosFromBottom1 + 1), strFormat1);
                            grPhoto1.DrawString(tempstr, crFont1, semiTransBrush1, new PointF(xCenterOfImg1, imgState.YPosFromBottom1), strFormat1);
                        }
                        else
                        {
                            grPhoto1.DrawString(imgState.TestoFirmaPiccola, crFont1, semiTransBrush21, new PointF(xCenterOfImg1 + 1, imgState.YPosFromBottom1 + 1), strFormat1);
                            grPhoto1.DrawString(imgState.TestoFirmaPiccola, crFont1, semiTransBrush1, new PointF(xCenterOfImg1, imgState.YPosFromBottom1), strFormat1);
                        }

                        // Salva la miniatura
                        //using (var g22 = Image.FromHbitmap(imgOutputSmall))


                        using var imgOutputSmall2 = new Bitmap(imgOutputSmall, imgState.ThumbSizeSmall.Width, imgState.ThumbSizeSmall.Height);
                        imgOutputSmall2.Save(Path.Combine(imgState.DestDir.FullName, imgState.NomeFileSmall), thisFormat);

                        //imgOutputSmall2.Dispose();

                        //imgOutputSmall.Dispose();


                        //File.Delete(Path.Combine(DestDir.FullName, "Temp_" + nomeFileSmall));
                        //FileSystem.Kill();
                    }
                    else
                    {
                        using var imgOutputSmall = new Bitmap(g, imgState.ThumbSizeSmall.Width, imgState.ThumbSizeSmall.Height);
                        imgOutputSmall.Save(Path.Combine(imgState.DestDir.FullName, imgState.NomeFileSmall), thisFormat);
                        //imgOutputSmall.Dispose();
                    }
                }
                else
                {
                    using var imgOutputSmall = new Bitmap(g, imgState.ThumbSizeSmall.Width, imgState.ThumbSizeSmall.Height);
                    imgOutputSmall.Save(Path.Combine(imgState.DestDir.FullName, imgState.NomeFileSmall), thisFormat);
                    //imgOutputSmall.Dispose();
                }
            }
        }

        crFont1?.Dispose();
        crFont2?.Dispose();
    }

    private void AggiungiTesto(Image g, ImageState imgState, Bitmap imgOutputBig)
    {
        using var grPhoto = Graphics.FromImage(imgOutputBig);
        grPhoto.SmoothingMode = SmoothingMode.AntiAlias;

        Font crFont = null/* TODO Change to default(_) if this is not a reference type */;

        if (picSettings.Grassetto == true)
            crFont = new Font(picSettings.IlFont, imgState.DimensioneStandard, FontStyle.Bold);
        else
            crFont = new Font(picSettings.IlFont, imgState.DimensioneStandard);
        var crSize = grPhoto.MeasureString(imgState.TestoFirma, crFont);
        var larghezzaStandard = System.Convert.ToInt32(crSize.Width);

        if (crSize.Width > System.Convert.ToSingle(g.Width))
        {
            var conta = imgState.DimensioneStandard;
            do
            {
                if (conta > 20)
                    conta -= 5;
                else
                    conta -= 1;
                if (picSettings.Grassetto == true)
                    crFont = new Font(picSettings.IlFont, conta, FontStyle.Bold);
                else
                    crFont = new Font(picSettings.IlFont, conta);
                crSize = grPhoto.MeasureString(imgState.TestoFirma, crFont);
                if (crSize.Width < System.Convert.ToSingle(g.Width))
                {
                    larghezzaStandard = System.Convert.ToInt32(crSize.Width);
                    break;
                }

                if (conta <= 5)
                    break;
            }
            while (true);
            imgState.DimensioneStandard = conta;
        }
        
        switch (picSettings.Posizione.ToUpper())
        {
            case "ALTO":
            {
                imgState.YPosFromBottom = (picSettings.Margine);
                imgState.YPosFromBottom3 = (picSettings.MargVert);
                break;
            }

            case "BASSO":
            {
                imgState.YPosFromBottom = System.Convert.ToSingle((g.Height - crSize.Height - (g.Height * picSettings.Margine / (double)100)));
                imgState.YPosFromBottom3 = System.Convert.ToSingle((g.Height - crSize.Height - (g.Height * picSettings.MargVert / (double)100)));
                break;
            }
        }

        float xCenterOfImg = 0;
        float xCenterOfImg3 = 0;
        using var strFormat = new StringFormat();
        switch (picSettings.Allineamento.ToUpper())
        {
            case "SINISTRA":
            {
                xCenterOfImg = System.Convert.ToSingle((picSettings.Margine + (larghezzaStandard / (double)2)));
                xCenterOfImg3 = System.Convert.ToSingle((picSettings.MargVert + (larghezzaStandard / (double)2)));
                if ((larghezzaStandard / (double)2) > (g.Width / (double)2) - picSettings.Margine)
                    xCenterOfImg = System.Convert.ToSingle((g.Width / (double)2));
                if ((larghezzaStandard / (double)2) > (g.Width / (double)2) - picSettings.MargVert)
                    xCenterOfImg3 = System.Convert.ToSingle((g.Width / (double)2));
                break;
            }

            case "CENTRO":
            {
                xCenterOfImg = System.Convert.ToSingle((g.Width / (double)2));
                break;
            }

            case "DESTRA":
            {
                xCenterOfImg = System.Convert.ToSingle((g.Width - picSettings.Margine - (larghezzaStandard / (double)2)));
                xCenterOfImg3 = System.Convert.ToSingle((g.Width - picSettings.MargVert - (larghezzaStandard / (double)2)));
                if ((larghezzaStandard / (double)2) > (g.Width / (double)2) - picSettings.Margine)
                    xCenterOfImg = System.Convert.ToSingle((g.Width / (double)2));
                if ((larghezzaStandard / (double)2) > (g.Width / (double)2) - picSettings.MargVert)
                    xCenterOfImg3 = System.Convert.ToSingle((g.Width / (double)2));
                break;
            }
        }
        strFormat.Alignment = StringAlignment.Center;

        using var semiTransBrush2 = new SolidBrush(Color.FromArgb(imgState.AlphaScelta, 0, 0, 0));
        // Dim semiTransBrush As SolidBrush = New SolidBrush(Color.FromArgb(AlphaScelta, _FontColoreR, _FontColoreG, _FontColoreB))
        using var semiTransBrush = new SolidBrush(Color.FromArgb(imgState.AlphaScelta, picSettings.FontColoreRGB));

        if (imgState.FotoRuotaADestra | imgState.FotoRuotaASinistra)
        {
            if (picSettings.Grassetto == true)
                crFont = new Font(picSettings.IlFont, picSettings.DimVert, FontStyle.Bold);
            else
                crFont = new Font(picSettings.IlFont, picSettings.DimVert);
        }
        else if (picSettings.Grassetto == true)
            crFont = new Font(picSettings.IlFont, imgState.DimensioneStandard, FontStyle.Bold);
        else
            crFont = new Font(picSettings.IlFont, imgState.DimensioneStandard);


        // qui scrive il testo (nomefilebig)
        if (picSettings.TestoNome)
        {
            if (picSettings.NomeData & g.PropertyIdList.Length > 0)
            {
                //ExifReader DatiExif = new ExifReader((Bitmap)g);
                imgState.DataFoto = imgState.CreationDate ?? DateTime.Now; //DatiExif.DateTimeOriginal;

                grPhoto.DrawString((imgState.NomeFileBig + " " + imgState.DataFoto.ToShortDateString()), crFont, semiTransBrush2, new PointF(xCenterOfImg + 1, imgState.YPosFromBottom + 1), strFormat);
                grPhoto.DrawString((imgState.NomeFileBig + " " + imgState.DataFoto.ToShortDateString()), crFont, semiTransBrush, new PointF(xCenterOfImg, imgState.YPosFromBottom), strFormat);
            }
            else
            {
                grPhoto.DrawString(imgState.NomeFileBig, crFont, semiTransBrush2, new PointF(xCenterOfImg + 1, imgState.YPosFromBottom + 1), strFormat);
                grPhoto.DrawString(imgState.NomeFileBig, crFont, semiTransBrush, new PointF(xCenterOfImg, imgState.YPosFromBottom), strFormat);
            }
        }

        if (picSettings.TestoNome == false)
        {
            if (imgState.FotoRuotaADestra | imgState.FotoRuotaASinistra)
            {
                if (picSettings.TestoMin == false)
                {
                    grPhoto.DrawString(imgState.TestoFirmaV, crFont, semiTransBrush2, new PointF(xCenterOfImg + 1, imgState.YPosFromBottom3 + 1), strFormat);
                    grPhoto.DrawString(imgState.TestoFirmaV, crFont, semiTransBrush, new PointF(xCenterOfImg, imgState.YPosFromBottom3), strFormat);
                }
                if (picSettings.TestoMin == true)
                {
                    grPhoto.DrawString(imgState.TestoFirmaV, crFont, semiTransBrush2, new PointF(xCenterOfImg + 1, imgState.YPosFromBottom4 + 1), strFormat);
                    grPhoto.DrawString(imgState.TestoFirmaV, crFont, semiTransBrush, new PointF(xCenterOfImg, imgState.YPosFromBottom4), strFormat);
                }
            }
            else
            {
                grPhoto.DrawString(imgState.TestoFirma, crFont, semiTransBrush2, new PointF(xCenterOfImg + 1, imgState.YPosFromBottom + 1), strFormat);
                grPhoto.DrawString(imgState.TestoFirma, crFont, semiTransBrush, new PointF(xCenterOfImg, imgState.YPosFromBottom), strFormat);
            }
        }

        if (string.Equals(picSettings.DirectorySorgente, picSettings.DirectoryDestinazione, StringComparison.OrdinalIgnoreCase))
        {
            imgState.NomeFileBig2 = imgState.NomeFileBig;
            imgState.NomeFileBig = $"{imgState.NomeFileBig[..^4]}{picSettings.Codice}{imgState.NomeFileBig[^4..]}";
        }
        //grPhoto.Dispose();

        crFont?.Dispose();
    }

    private void AggiungiLogo(Bitmap imgOutputBig, ImageState imgState, Image logo)
    {
        // imgOutputBig
        if (!(picSettings.LogoAggiungi == true & File.Exists(picSettings.LogoNomeFile))) return;
        // using var ImmagineLogo = Image.FromFile(_picSettings.LogoNomeFile);

        var logoColoreTrasparente = Color.White;

        // * Load this Bitmap into a new Graphic Object
        using var grWatermark = Graphics.FromImage(imgOutputBig);
        using ImageAttributes imageAttributes = new ImageAttributes();

        // * The first step replace the background color with one that is transparent (Alpha=0, R=0, G=0, B=0)
        var colorMap = new ColorMap
        {
            // * background this will be the color we search for and replace with transparency
            OldColor = logoColoreTrasparente,
            NewColor = Color.FromArgb(0, 0, 0, 0)
        };

        var remapTable = new[] { colorMap };
        imageAttributes.SetRemapTable(remapTable, ColorAdjustType.Bitmap);

        // * The second color manipulation is used to change the opacity by setting the 3rd row and 3rd column to 0.3f
        var colorMatrixElements = new[] { new float[] { 1.0F, 0.0F, 0.0F, 0.0F, 0.0F }, new float[] { 0.0F, 1.0F, 0.0F, 0.0F, 0.0F }, new float[] { 0.0F, 0.0F, 1.0F, 0.0F, 0.0F }, new float[] { 0.0F, 0.0F, 0.0F, System.Convert.ToSingle(picSettings.LogoTrasparenza) / 100F, 0.0F }, new float[] { 0.0F, 0.0F, 0.0F, 0.0F, 1.0F } };
        var wmColorMatrix = new ColorMatrix(colorMatrixElements);
        imageAttributes.SetColorMatrix(wmColorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);

        var fotoLogoH = picSettings.LogoAltezza;
        var fotoLogoW = picSettings.LogoLarghezza;
        var fattoreAlt = logo.Height / (double)fotoLogoH;
        var fattoreLarg = logo.Width / (double)fotoLogoW;
        var nuovaSize = fattoreLarg > fattoreAlt ? NewthumbSize(logo.Width, logo.Height, fotoLogoW, "Larghezza") : NewthumbSize(logo.Width, logo.Height, fotoLogoH, "Altezza");

        var inPercentualeL = picSettings.LogoMargine.EndsWith('%');
        var margineL = System.Convert.ToInt32(picSettings.LogoMargine);
        var margineUsato = inPercentualeL ? System.Convert.ToInt32(imgOutputBig.Height * margineL / (double)100) : margineL;

        int xPosOfWm = 0;
        int yPosOfWm = 0;
        switch (picSettings.LogoPosizioneH.ToUpper())
        {
            case "SINISTRA":
            case "NESSUNA":
            {
                xPosOfWm = margineUsato;
                break;
            }

            case "CENTRO":
            {
                xPosOfWm = System.Convert.ToInt32((imgOutputBig.Width - nuovaSize.Width) / (double)2);
                break;
            }

            case "DESTRA":
            {
                xPosOfWm = ((imgOutputBig.Width - nuovaSize.Width) - margineUsato);
                break;
            }
        }
        switch (picSettings.LogoPosizioneV.ToUpper())
        {
            case "ALTO":
            case "NESSUNA":
            {
                yPosOfWm = margineUsato;
                break;
            }

            case "CENTRO":
            {
                yPosOfWm = System.Convert.ToInt32((imgOutputBig.Height - nuovaSize.Height) / (double)2);
                break;
            }

            case "BASSO":
            {
                yPosOfWm = ((imgOutputBig.Height - nuovaSize.Height) - margineUsato);
                break;
            }
        }

        grWatermark.DrawImage(logo, new Rectangle(xPosOfWm, yPosOfWm, nuovaSize.Width, nuovaSize.Height), 0, 0, logo.Width, logo.Height, GraphicsUnit.Pixel, imageAttributes);
        //grWatermark.Dispose();
    }


    private void SalvaFoto(Bitmap imgOutputBig, ImageState imgState, ImageFormat thisFormat)
    {
        using var image1Stream = new MemoryStream();
        if (picSettings.FotoGrandeDimOrigina == false)
        {
            // attenzione non controlla se è png
            // imgOutputBig.Save(Path.Combine(_DestDir.FullName, "Temp_" & NomeFileBig), thisFormat)
            if (thisFormat.Equals(ImageFormat.Jpeg))
            {
                MakeImageCustomQuality(imgOutputBig, image1Stream);
            }
            //SalvaImmagineCustomQuality(imgOutputBig, Path.Combine(DestDir.FullName, "Temp_" + NomeFileBig), _picSettings.jpegQuality);
            else
            {
                imgOutputBig.Save(image1Stream, thisFormat);
            }
            //imgOutputBig.Save(Path.Combine(DestDir.FullName, "Temp_" + NomeFileBig), thisFormat);
            image1Stream.Seek(0, SeekOrigin.Begin);
            using var g2 = Image.FromStream(image1Stream);
            imgState.ThumbSizeBig = g2.Width > g2.Height ? NewthumbSize(g2.Width, g2.Height, picSettings.LarghezzaBig, "Larghezza") : NewthumbSize(g2.Width, g2.Height, picSettings.AltezzaBig, "Altezza");
            using var imgOutputBig2 = new Bitmap(g2, imgState.ThumbSizeBig.Width, imgState.ThumbSizeBig.Height);
            if (thisFormat.Equals(ImageFormat.Jpeg))
                SalvaImmagineCustomQuality(imgOutputBig2, Path.Combine(imgState.DestDir.FullName, imgState.NomeFileBig), picSettings.JpegQuality);
            else
                imgOutputBig2.Save(Path.Combine(imgState.DestDir.FullName, imgState.NomeFileBig), thisFormat);

            //imgOutputBig2.Dispose();

            //imgOutputBig.Dispose();
            //g2.Dispose();
        }
        else
        {
            // 
            if (thisFormat.Equals(ImageFormat.Jpeg))
                SalvaImmagineCustomQuality(imgOutputBig, Path.Combine(imgState.DestDir.FullName, imgState.NomeFileBig), picSettings.JpegQuality);
            else
                imgOutputBig.Save(Path.Combine(imgState.DestDir.FullName, imgState.NomeFileBig), thisFormat);

            //imgOutputBig.Dispose();
        }
        image1Stream.Seek(0, SeekOrigin.Begin);

        if (!picSettings.CreaMiniature) return;
        if (!picSettings.AggiungiScritteMiniature) return;
        using var g1 = picSettings.FotoGrandeDimOrigina ? (Image)imgOutputBig.Clone() : Image.FromStream(image1Stream);
        //if (_picSettings.FotoGrandeDimOrigina == false)
        //    g1 = Image.FromStream(image1Stream);
        ////g1 = System.Drawing.Image.FromFile(Path.Combine(DestDir.FullName, "Temp_" + NomeFileBig));
        //else
        //    g1 = (Image)imgOutputBig.Clone();
        //g1 = System.Drawing.Image.FromFile(Path.Combine(DestDir.FullName, NomeFileBig));
        using Bitmap imgOutputSmall = new Bitmap(g1, imgState.ThumbSizeSmall.Width, imgState.ThumbSizeSmall.Height);
        if (string.Equals(picSettings.DirectorySorgente, picSettings.DirectoryDestinazione, StringComparison.OrdinalIgnoreCase))
            imgState.NomeFileSmall = imgState.NomeFileSmall.Substring(0, imgState.NomeFileSmall.Length - 4) + picSettings.Codice + imgState.NomeFileSmall.Substring(imgState.NomeFileSmall.Length - 4);
        // 
        if (thisFormat.Equals(ImageFormat.Jpeg))
            SalvaImmagineCustomQuality(imgOutputSmall, Path.Combine(imgState.DestDir.FullName, imgState.NomeFileSmall), picSettings.JpegQualityMin);
        else
            imgOutputSmall.Save(Path.Combine(imgState.DestDir.FullName, imgState.NomeFileSmall), thisFormat);

        //imgOutputSmall.Dispose();

        //g1.Dispose();

        //if (File.Exists(Path.Combine(DestDir.FullName, "Temp_" + NomeFileBig)))
        //    File.Delete(Path.Combine(DestDir.FullName, "Temp_" + NomeFileBig));
    }

    private void SalvaImmagineCustomQuality(Bitmap imageToSave, string nomeFileFinale, long quality)
    {
        var jgpEncoder = GetEncoder(ImageFormat.Jpeg);
        var myEncoder = System.Drawing.Imaging.Encoder.Quality;

        using var myEncoderParameters = new EncoderParameters(1);

        var myEncoderParameter = new EncoderParameter(myEncoder, picSettings.JpegQuality);
        myEncoderParameters.Param[0] = myEncoderParameter;
        imageToSave.Save(nomeFileFinale, jgpEncoder, myEncoderParameters);
        //imageToSave.Dispose();
    }

    private void MakeImageCustomQuality(Bitmap imageToSave, Stream destinationStream)
    {
        var jgpEncoder = GetEncoder(ImageFormat.Jpeg);
        var myEncoder = System.Drawing.Imaging.Encoder.Quality;

        using var myEncoderParameters = new EncoderParameters(1);

        var myEncoderParameter = new EncoderParameter(myEncoder, picSettings.JpegQuality);
        myEncoderParameters.Param[0] = myEncoderParameter;
        destinationStream.Seek(0, SeekOrigin.Begin);
        imageToSave.Save(destinationStream, jgpEncoder, myEncoderParameters);
        //imageToSave.Dispose();
    }
    
    private ImageCodecInfo GetEncoder(ImageFormat format)
    {
        var codecs = ImageCodecInfo.GetImageDecoders();
        
        foreach (var codec in codecs)
        {
            if (codec.FormatID == format.Guid)
                return codec;
        }
        return null/* TODO Change to default(_) if this is not a reference type */;
    }
    
    /// <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;

        if (tipoSize.ToUpper() == "Larghezza".ToUpper())
            tempMultiplier = maxPixel / (double)currentwidth;
        else if (tipoSize.ToUpper() == "Altezza".ToUpper())
            tempMultiplier = maxPixel / (double)currentheight;
        else if (currentheight > currentwidth)
            tempMultiplier = maxPixel / (double)currentheight;
        else
            tempMultiplier = maxPixel / (double)currentwidth;

        var newSize = new Size(System.Convert.ToInt32(currentwidth * tempMultiplier), System.Convert.ToInt32(currentheight * tempMultiplier));

        return newSize;
    }

  
}