using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Data.SqlClient;
using System.IO;
using System.Net;
using System.Threading;
using System.Configuration;
using System.Xml;
using System.Web;
using System.Collections.Concurrent;
using System.Diagnostics;
using Amazon;
using Amazon.S3;
using Amazon.S3.Model;
using Amazon.S3.Transfer;
using Amazon.S3.IO;
using Amazon.CloudFront.Model;
using Amazon.CloudFront;

namespace BwandBlocking
{
    public partial class Form1 : Form
    {
        #region variables
        public DataTable t1 = new DataTable();
        private static List fileNames = new List();
        public static BackgroundWorker bw = new BackgroundWorker();
        public static Image img;
        public static ImageFileName FileNameImage;
        public static BlockingCollection bc;
        public static int percentComplete;
        private static S3 s3 = new S3(S3Bucket.WebContent);
        public const int size = 10;
        public static int count = 0;
        public decimal featherValue;
        public bool boxChecked;
        #endregion

        public Form1()
        {
            InitializeComponent();
            bw.WorkerSupportsCancellation = true;
            bw.WorkerReportsProgress = true;
            bw.DoWork += new DoWorkEventHandler(bw_DoWork);
            bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
            bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
            featherValue = numericUpDown.Value;
            boxChecked = false;
        }

        private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
        }

        private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            progressBar2.Value = 0;
            if (e.Cancelled == true)
            {
                textBoxErrorDisplay.Text = "Operation Cancelled..";
            }
        }

        private void button_Access_Click(object sender, EventArgs e)
        {
            using (SqlConnection connection = new SqlConnection("Data Source=gpasql.d2go.net; UID=kulkag; pwd=GrasscoaCh2;Initial Catalog=GPAWebSite"))
            {
                connection.Open();
                using (SqlCommand cm = new SqlCommand("SELECT Filename FROM GPAWebSite.dbo.Images WHERE (Type = '.ra1'"
                + "OR Type = '.ra2'"
                + "OR Type = '.ra3'"
                + "OR Type = '.ra4'"
                + "OR Type = '.ra5'"
                + "OR Type = '.ra6'"
                + "OR Type = '.rw'"
                + "OR Type = '.renv');", connection))
                {
                    t1.Load(cm.ExecuteReader());
                    foreach (DataRow row in t1.Rows)
                    {
                        fileNames.Add(row["Filename"].ToString());
                    }
                }
                Console.WriteLine("Size of List : {0}", fileNames.Count);
            }
        }

        private void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            using (bc = new BlockingCollection(size)) //Size - defines maximum size of Producer queue. Max Limit = 40
            {
                Task task1 = Task.Factory.StartNew(() => DownloadImage());
                Task task2 = Task.Factory.StartNew(() =>
                           {
                               #region SaveImage
                               int countImage = 0;
                               foreach (ImageFileName imgfilename2 in bc.GetConsumingEnumerable())
                               {
                                   if (bw.CancellationPending == true)
                                   {
                                       e.Cancel = true;
                                       break;
                                   }
                                   else
                                   {
                                       Image originalImage = imgfilename2.Image;
                                       string filenameWOExtension = Path.GetFileNameWithoutExtension(imgfilename2.ImageName).ToLower();
                                       string extension = Path.GetExtension(imgfilename2.ImageName).ToLower();
                                       ledBulb2.Blink(20);
                                       Image zoomThumbnail = ImageUtility.GenerateThumbnail(originalImage, 86, false, featherValue, boxChecked);
                                       Image zoomSmall = ImageUtility.GenerateThumbnail(originalImage, 400, false, featherValue, boxChecked);
                                       Image zoomLarge = ImageUtility.GenerateThumbnail(originalImage, 1200, false, featherValue, boxChecked);
                                       ledBulb2.Blink(0);
                                       originalImage.Dispose();

                                       try
                                       {
                                           if (zoomThumbnail != null)
                                           {
                                               string newFilenameThumb = String.Format("{0}_thumb{1}", filenameWOExtension, extension);
                                               s3.Upload(zoomThumbnail.ToStream(System.Drawing.Imaging.ImageFormat.Jpeg), "images/zoom/" + newFilenameThumb, false); //syncUpload
                                               zoomThumbnail.Dispose();
                                           }
                                           if (zoomSmall != null)
                                           {
                                               string newFilenamePreview = String.Format("{0}_preview{1}", filenameWOExtension, extension);
                                               s3.Upload(zoomSmall.ToStream(System.Drawing.Imaging.ImageFormat.Jpeg), "images/zoom/" + newFilenamePreview, false); //syncUpload
                                               zoomSmall.Dispose();
                                           }
                                           if (zoomLarge != null)
                                           {
                                               string newFilenameZoom = String.Format("{0}_zoom{1}", filenameWOExtension, extension);
                                               s3.Upload(zoomLarge.ToStream(System.Drawing.Imaging.ImageFormat.Jpeg), "images/zoom/" + newFilenameZoom, false); //syncUpload
                                               zoomLarge.Dispose();
                                           }
                                           countImage++;
                                           textBoxImagesProcessed.BeginInvoke((MethodInvoker)delegate { textBoxImagesProcessed.Text = countImage.ToString() + "/" + fileNames.Count; });
                                           progressBar2.BeginInvoke((MethodInvoker)delegate { progressBar2.Maximum = fileNames.Count; });
                                           progressBar2.BeginInvoke((MethodInvoker)delegate { progressBar2.Increment(1); });
                                       }
                                       catch (Exception ex)
                                       {
                                           e.Cancel = true;
                                           e.Result = ex;
                                       }
                                   }
                                   GC.Collect();
                                   Console.WriteLine("Item Consumed: {0}", bc.Count);
                               }
                               #endregion
                           });
                Task.WaitAll(task1);
                bc.CompleteAdding();
                Task.WaitAll(task2);
            }
        }
        /// 
        /// Method to download Image from S3 Bucket and insert into BlockingCollection bc
        /// 
        private void DownloadImage()
        {
            HttpWebRequest request = null;
            foreach (var fileName in fileNames)
            {
                string baseUrl = "http://gpawebcontent.s3.amazonaws.com/images/{0}";
                string url = string.Format(baseUrl, fileName);

             try
                {
                    request = (HttpWebRequest)WebRequest.Create(url);
                    request.Method = "GET";
                    request.ContentType = "application/x-www-form-urlencoded";
                    using (var response = (HttpWebResponse)request.GetResponse())
                    {
                        using (Stream stream = response.GetResponseStream())
                        {
                            var responsecode = response.StatusCode;
                            img = Image.FromStream(stream);
                            ledBulb1.Blink(200);
                            FileNameImage = new ImageFileName(fileName.ToString(), img);
                            bc.Add(FileNameImage);
                        }
                    }
                    ledBulb1.Blink(0);
                    Console.WriteLine("Item Added: {0}", bc.Count);
                }
                catch (WebException wEx)
                {
                    HttpWebResponse errorResponse = wEx.Response as HttpWebResponse;
                    if (errorResponse.StatusCode == HttpStatusCode.NotFound)
                    {
                        string exceptionfile = String.Format("{0} : {1} {2}",
                            fileName,
                            (int)((HttpWebResponse)wEx.Response).StatusCode,
                            ((HttpWebResponse)wEx.Response).StatusDescription);
                        textBoxErrorDisplay.BeginInvoke((MethodInvoker)delegate { textBoxErrorDisplay.Text = exceptionfile; });
                        count++;
                    }
                    textBoxCount.BeginInvoke((MethodInvoker)delegate { textBoxCount.Text = count.ToString(); });
                }
                catch (Exception ex)
                {
                    textBoxErrorDisplay.BeginInvoke((MethodInvoker)delegate { textBoxErrorDisplay.Text = ex.Message; });
                }
            }
        }

       private void button_Start_Click(object sender, System.EventArgs e)
        {
            BackgroundWorker bgWorker = new BackgroundWorker();
            bgWorker.DoWork += bw_DoWork;
            bgWorker.RunWorkerCompleted += bw_RunWorkerCompleted;
            bgWorker.ProgressChanged += bw_ProgressChanged;
            bgWorker.WorkerSupportsCancellation = true;
            bgWorker.WorkerReportsProgress = true;
            Button btnSender = (Button)sender;
            btnSender.Enabled = false;
            bgWorker.RunWorkerAsync();
        }

        private void button_Cancel_Click(object sender, System.EventArgs e)
        {
            Button btnSender = (Button)sender;
            btnSender.Enabled = false;
            bw.CancelAsync();
        }

        private void button_Exit_Click(object sender, EventArgs e)
        {
            Application.Exit();
            button_Access.Enabled = true;
            button_Start.Enabled = true;

        }

        private void checkBoxRound_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBoxRound.Checked == true)
            {
                boxChecked = true;
                checkBoxFeather.Enabled = true;
            }
            else
            {
                boxChecked = false;
                checkBoxFeather.Enabled = false;
                numericUpDown.Enabled = false;
                numericUpDown.Value = 0;
                checkBoxFeather.Checked = false;
            }
        }

        private void checkBoxFeather_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBoxFeather.Checked == true)
            {
                numericUpDown.Enabled = true;
            }
            else
            {
                numericUpDown.Enabled = false;
                numericUpDown.Value = 0;
            }
        }
    }

    public class ImageData
    {
        public int ImageID { get; set; }
        public string Filename { get; set; }
        public string Type { get; set; }
        public int Width { get; set; }
        public int Height { get; set; }
        public string Description { get; set; }
        public ImageData()
        {
        }

        public ImageData(int imageId, string filename, string type, int width, int height, string description)
        {
            ImageID = imageId;
            Filename = filename;
            Type = type;
            Width = width;
            Height = height;
            Description = description;
        }
    }

    public class ImageFileName
    {
        public string ImageName { get; set; }
        public Image Image { get; set; }
        public ImageFileName(string imageName, Image image)
        {
            ImageName = imageName;
            Image = image;
        }
    }
}