using Amazon;
using Amazon.Rekognition;
using Amazon.Rekognition.Model;
using Amazon.Runtime;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace ComparerVisages
{
   public partial class MainWindow : Window
    {
		//******************************
		//Definir région et clés d'accès
		//******************************
		private RegionEndpoint AWSreg = RegionEndpoint.EUWest1;
		private static readonly string accessKey = "";
		private static readonly string secretKey = "";
        private BasicAWSCredentials AWSCred = new BasicAWSCredentials(accessKey, secretKey);

		private BitmapSource imageSource;
        private Stream stream = null;
        private Stream streamSource = null;
        private Stream streamCible = null;
        Amazon.Rekognition.Model.Image imageSourceReko = null;
        Amazon.Rekognition.Model.Image imageCibleReko = null;
        private string pathsource = "";
        private string pathcible = "";
        int orientationjpg = 0;
        private BackgroundWorker backgroundWorker1 = new BackgroundWorker();
        private BackgroundWorker backgroundWorker2 = new BackgroundWorker();

        public MainWindow()
        {
            InitializeComponent();
        }

        public BitmapSource imageAffiche(Stream stream, bool source)
        {
            orientationjpg = 0;
            stream.Position = 0;
            BitmapFrame bitmapFrame = BitmapFrame.Create(stream, BitmapCreateOptions.DelayCreation, BitmapCacheOption.None);
            BitmapMetadata bitmapMetadata = bitmapFrame.Metadata as BitmapMetadata;

            if ((bitmapMetadata != null) && (bitmapMetadata.ContainsQuery("System.Photo.Orientation")))
            {
                object o = bitmapMetadata.GetQuery("System.Photo.Orientation");

                if (o != null)
                {
                    switch ((ushort)o)
                    {
                        case 6:
                            orientationjpg = 90;
                            break;
                        case 3:
                            orientationjpg = 180;
                            break;
                        case 8:
                            orientationjpg = 270;
                            break;
                    }
                }
            }

            string path = "";
            if (source) { path = pathsource; } else { path = pathcible; }
            imageSource = new BitmapImage(new Uri(path));
            if (orientationjpg != 0)
            {
                TransformedBitmap tb = new TransformedBitmap();
                tb.BeginInit();
                tb.Source = imageSource;
                RotateTransform transform = new RotateTransform(orientationjpg);
                tb.Transform = transform;
                tb.EndInit();
                return tb;
            }
            else
            {
                return imageSource;
            }
        }

        public Amazon.Rekognition.Model.Image GetImageFromFile(bool source)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();

			//Définir répertoire source des images
			openFileDialog.InitialDirectory = "";

            openFileDialog.ShowDialog();
            if (source) { pathsource = openFileDialog.FileName; }
            else { pathcible = openFileDialog.FileName; }

            Amazon.Rekognition.Model.Image image = new Amazon.Rekognition.Model.Image();
            try
            {
                stream = openFileDialog.OpenFile();

                byte[] data = new byte[stream.Length];
                stream.Read(data, 0, (int)stream.Length);
                image.Bytes = new MemoryStream(data);
                stream.Position = 0;
                if (source) { streamSource = stream; } else { streamCible = stream; }
                return image;
            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString());
                return null;
            }

        }

        public void ComparerVisages()
        {
            BoundingBox bb;
            AmazonRekognitionClient rekCli = new AmazonRekognitionClient(AWSCred, AWSreg);

			//Création de la requête de comparaison de visages
            CompareFacesRequest compareFacesRequest = new CompareFacesRequest()
            {
                SourceImage = imageSourceReko,
                TargetImage = imageCibleReko,
                SimilarityThreshold = (float)75
            };

			//Lancement de la comparaison de visages
            CompareFacesResponse compareFacesResponse = new AmazonRekognitionClient(AWSCred, AWSreg).CompareFaces(compareFacesRequest);
            ComparedSourceImageFace sourceImageFace = compareFacesResponse.SourceImageFace;

			//Affichage des cadres autour des visages analysés
			bb = sourceImageFace.BoundingBox;
            AfficheCadre(streamSource, true, bb.Left, bb.Top, bb.Width, bb.Height);
            List<CompareFacesMatch> compareFaces = compareFacesResponse.FaceMatches;
            
            foreach (CompareFacesMatch compare in compareFaces)
            {
                if (compare.Similarity > 90)
                {
                    bb = compare.Face.BoundingBox;
                    AfficheCadre(streamCible, false, bb.Left, bb.Top, bb.Width, bb.Height);
                    txtSimilarite.Text = $"Similarité = {compare.Similarity}%";
                }
                if (txtSimilarite.Text == "") { txtSimilarite.Text = "Aucune similarité trouvée"; }

            }
        }

        public void AfficheCadre(Stream stream, bool source, float x, float y, float w, float h)
        {
            stream.Position=0;
            BitmapSource bitmap;
            if (source)
            {
                bitmap = (BitmapSource)imgSource.Source;
            }
            else
            {
                bitmap = (BitmapSource)imgCible.Source;
            }
            DrawingVisual dv = new DrawingVisual();
            using (DrawingContext dc = dv.RenderOpen())
            {
                dc.DrawImage(bitmap, new Rect(0, 0, bitmap.PixelWidth, bitmap.PixelHeight));
                dc.DrawRectangle(null, new Pen(Brushes.Cyan, 2), new Rect(x * bitmap.PixelWidth, y * bitmap.PixelHeight, w * bitmap.PixelWidth, h * bitmap.PixelHeight));
            }
            RenderTargetBitmap rtb = new RenderTargetBitmap(bitmap.PixelWidth, bitmap.PixelHeight, 96, 96, PixelFormats.Pbgra32);
            rtb.Render(dv);
            if (source) { imgSource.Source = rtb; } else { imgCible.Source = rtb; }
        }

        private void BtnSource_Click(object sender, RoutedEventArgs e)
        {
            imageSourceReko=GetImageFromFile(true);
            imgSource.Source = imageAffiche(streamSource, true);
            btnSource.IsEnabled = false;
            btnCible.IsEnabled = true;
        }

        private void BtnCible_Click(object sender, RoutedEventArgs e)
        {
            imageCibleReko=GetImageFromFile(false);
            imgCible.Source=imageAffiche(streamCible, false);
            btnCible.IsEnabled = false;
            btnReko.IsEnabled = true;
        }

        private void btnReko_Click(object sender, RoutedEventArgs e)
        {
            txtSimilarite.Text = "";
            //backgroundWorker1.RunWorkerAsync();
            ComparerVisages();
            btnReko.IsEnabled = false;
            btnSource.IsEnabled = true;
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            for (int i = 1; i <= 100; i++)
            {
                Thread.Sleep(100);
                backgroundWorker1.ReportProgress(i);
            }
        }
        private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
        {
            ComparerVisages();
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            prbComparaison.Value = e.ProgressPercentage * 100;
        }
    }
}
