using System;
using System.Net;
using System.Windows;
using System.Text;
using System.Security.Cryptography;
using System.IO.IsolatedStorage;
using System.IO;
using System.Windows.Media.Imaging;

namespace WPImageCaching
{
    internal static class ImageDownloadHelper
    {
        private const double EXPIRATIONDAYS = 1.0;

        //Hilfsmethode zum Laden des Bildes
        public static void DownloadImage(string url, BitmapImage image, ImageCacheItem item)
        {
            string filename = CreateUniqueFilename(url);
            item.LocalFilename = filename;

            //Erstellen des Hilfsobjektes zur Übergabe an den asynchronen Aufruf
            AsyncDataTransfer transfer = new AsyncDataTransfer();
            transfer.Item = item;
            transfer.Image = image;

            //Erstellen der Abfrage
            var wc = (HttpWebRequest)HttpWebRequest.Create(url);
            if (item.ImageID!=null)
            {
                //Prüfen, ob das Bild im Web immer noch aktuell ist
                wc.Headers["If-None-Match"] = item.ImageID;
            }
            transfer.WebRequest = wc;

            wc.BeginGetResponse(RequestCallback, transfer);
        }

        private static void RequestCallback(IAsyncResult result)
        {
            //War die Abfrage erfolgreich
            if (!result.IsCompleted)
            {
                return;
            }

            //Herstellen des Hilfsobjektes
            AsyncDataTransfer transfer = (AsyncDataTransfer)result.AsyncState;
            try
            {
                var response = (HttpWebResponse)transfer.WebRequest.EndGetResponse(result);

                //Bild wurde nicht geändert seit dem letzten Aufruf
                if (response.StatusCode == HttpStatusCode.NotModified)
                {
                    Deployment.Current.Dispatcher.BeginInvoke(() => transfer.Image.SetSource(IsolatedStorageFile.GetUserStoreForApplication().OpenFile(transfer.Item.LocalFilename, FileMode.Open)));
                    return;
                }
                //Hat das Bild eine neue ID?
                if (response.Headers["ETag"] != null)
                {
                    transfer.Item.ImageID = response.Headers["ETag"];
                }
                else
                {
                    transfer.Item.ImageID = null;
                }
                //Gibt es ein Ablaufdatum?
                if (response.Headers["Expires"] != null)
                {
                    transfer.Item.Expiration = DateTime.Parse(response.Headers["Expires"]);
                }
                else
                {
                    transfer.Item.Expiration = DateTime.Now.AddDays(EXPIRATIONDAYS);
                }

                var responseStream = response.GetResponseStream();

                //Schreiben der Bilddatei
                using (var bw = new BinaryWriter(IsolatedStorageFile.GetUserStoreForApplication().CreateFile(transfer.Item.LocalFilename)))
                {
                    byte[] b = new byte[4096];
                    int read = 0;
                    while ((read = responseStream.Read(b, 0, b.Length)) > 0)
                    {
                        bw.Write(b, 0, read);
                    }
                    bw.Flush();
                    bw.Close();
                }
                //Setzen des Bildes
                Deployment.Current.Dispatcher.BeginInvoke(() => transfer.Image.SetSource(IsolatedStorageFile.GetUserStoreForApplication().OpenFile(transfer.Item.LocalFilename, FileMode.Open)));
                //Hinzufügen der Bildinformationen
                ImageCache.imageCache.Add(transfer.WebRequest.RequestUri.ToString(), transfer.Item);
                //Speichern der Bildinformationen
                ImageCache.SaveCachedImageInfo();
            }
            catch
            {
                //Nichts machen, da Bild nicht heruntergeladen werden konnte
            }
        }

        //Erstellt einen eindeutigen Namen für das zu ladende Bild
        private static string CreateUniqueFilename(string url)
        {
            string extension = System.IO.Path.GetExtension(url);
            byte[] textToHash = Encoding.UTF8.GetBytes(url);
            SHA1Managed sa = new SHA1Managed();
            byte[] hash = sa.ComputeHash(textToHash);
            return BitConverter.ToString(hash)+extension;
        }
    }
}
