using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Net;
using System.Xml;
using System.Xml.Serialization;

namespace EAT_IT
{
    using XTNs;
    using Windows.Data.Xml.Dom;
    using Windows.Storage;
    using Windows.Storage.Streams;

    public class Rezept
    {
        // Diese Klasse ist grundsätzlich dafür da, die aus dem internet ausgelesenen Rezepte zu speichern und zu katalogisieren.
        //Ferner enthält sie Speicher- und Öffnungsmethoden. Details in der beiliegenden Dokumentation.
        private XmlDocument RSSContent;
        XmlSerializer serializer;
        MyRecipe meinRezept;

        private string HTMLContent;

        public List<string> Zubereitung
        {
            get;
            set;
        }

        public List<string> Arbeitszeit
        {
            get;
            set;
        }

        public List<string> Ruhezeit
        {
            get;
            set;
        }

        public List<string> Schwierigkeit
        {
            get;
            set;
        }

        public List<int> Portionen
        {
            get;
            set;
        }

        public List<List<string>> Zutaten
        {
            get;
            set;
        }

        public List<List<double>> Zutatenmenge
        {
            get;
            set;
        }

        public List<List<string>> Zutateneinheit
        {
            get;
            set;
        }

        public List<string> RezeptURLs
        {
            get;
            set;
        }

        public List<string> Kurzbeschreibung
        {
            get;
            set;
        }

        public List<string> Titel
        {
            get;
            set;
        }

        public List<string> ImageURLs
        {
            get;
            set;
        }

        public Rezept()
        {
            RSSContent = new XmlDocument();
            Titel = new List<string>();
            ImageURLs = new List<string>();
            RezeptURLs = new List<string>();
            Zutaten = new List<List<string>>();
            Zutatenmenge = new List<List<double>>();
            Zutateneinheit = new List<List<string>>();
            Portionen = new List<int>();
            Arbeitszeit = new List<string>();
            Ruhezeit = new List<string>();
            Schwierigkeit = new List<string>();
            Zubereitung = new List<string>();
            Kurzbeschreibung = new List<string>();
            serializer = new XmlSerializer(typeof(MyRecipe));
            meinRezept = new MyRecipe();
        }
        public async Task Ratingchange(double Rating,string Dateiname)
        {
            MyRecipe meinRezept = new MyRecipe();
            meinRezept = await Opener(Dateiname);
            meinRezept.Rating = Rating;
            StorageFile store = await ApplicationData.Current.LocalFolder.CreateFileAsync(Dateiname, Windows.Storage.CreationCollisionOption.ReplaceExisting);
            IRandomAccessStream sessionRandomAccess = await store.OpenAsync(FileAccessMode.ReadWrite);
            IOutputStream sessionOutputStream = sessionRandomAccess.GetOutputStreamAt(0);
            var serializer = new XmlSerializer(typeof(MyRecipe));
            //Using DataContractSerializer , look at the cat-class
            //var sessionSerializer = new DataContractSerializer(typeof(List<object>), new Type[] { typeof(T) });
            //sessionSerializer.WriteObject(sessionOutputStream.AsStreamForWrite(), _data);

            //Using XmlSerializer , look at the Dog-class
            serializer.Serialize(sessionOutputStream.AsStreamForWrite(), meinRezept);
            sessionRandomAccess.Dispose();
            await sessionOutputStream.FlushAsync();
            sessionOutputStream.Dispose();




        }

        public async Task<string> Save(int auswahl)
        {
            Random myrandom = new Random();
                        int random = myrandom.Next(1, 10000000);
            string Dateiname = (auswahl+1)*random+".EAT";
            auswahl--;
            meinRezept.Titel = Titel[auswahl];
            meinRezept.Zutaten = Zutaten[auswahl];
            meinRezept.Zutatenmenge = Zutatenmenge[auswahl];
            meinRezept.Zutateneinheit = Zutateneinheit[auswahl];
            meinRezept.Portionen = Portionen[auswahl];
            meinRezept.Arbeitszeit = Arbeitszeit[auswahl];
            meinRezept.Ruhezeit = Ruhezeit[auswahl];
            meinRezept.Schwierigkeit = Schwierigkeit[auswahl];
            meinRezept.Zubereitung = Zubereitung[auswahl];
            meinRezept.Kurzbeschreibung = Kurzbeschreibung[auswahl];
            meinRezept.ImagePfad = ImageURLs[auswahl];
            meinRezept.Dateiname = Dateiname;
            
            StorageFile store = await ApplicationData.Current.LocalFolder.CreateFileAsync(Dateiname, Windows.Storage.CreationCollisionOption.ReplaceExisting);
            IRandomAccessStream sessionRandomAccess = await store.OpenAsync(FileAccessMode.ReadWrite);
            IOutputStream sessionOutputStream = sessionRandomAccess.GetOutputStreamAt(0);
            var serializer = new XmlSerializer(typeof(MyRecipe));
            //Using DataContractSerializer , look at the cat-class
            //var sessionSerializer = new DataContractSerializer(typeof(List<object>), new Type[] { typeof(T) });
            //sessionSerializer.WriteObject(sessionOutputStream.AsStreamForWrite(), _data);

            //Using XmlSerializer , look at the Dog-class
            serializer.Serialize(sessionOutputStream.AsStreamForWrite(), meinRezept);
            sessionRandomAccess.Dispose();
            await sessionOutputStream.FlushAsync();
            sessionOutputStream.Dispose();
            return Dateiname;
            
        }

        public async Task<MyRecipe> Opener(string Datei)
        {
            
            //StorageFile sessionFile = await ApplicationData.Current.LocalFolder.CreateFileAsync("lolerskates", CreationCollisionOption.OpenIfExists);
            //if (sessionFile == null)
            //{
            //    return null;
            //}
            //IInputStream sessionInputStream = await sessionFile.OpenReadAsync();
            var sessionInputStream = (await ApplicationData.Current.LocalFolder.OpenStreamForReadAsync(Datei));

            //Using DataContractSerializer , look at the cat-class
            // var sessionSerializer = new DataContractSerializer(typeof(List<object>), new Type[] { typeof(T) });
            //_data = (List<object>)sessionSerializer.ReadObject(sessionInputStream.AsStreamForRead());

            //Using XmlSerializer , look at the Dog-class
            //byte[] buffer = new byte[100];
            //sessionInputStream.Read(buffer, 0, 100);
            //var temp = buffer.Select(b => (char)b).ToArray();
            try
            {
                meinRezept = (MyRecipe)serializer.Deserialize(sessionInputStream);
            }
            catch (Exception)
            {
                
                throw;
            }
            sessionInputStream.Dispose();
            return meinRezept;

        }

        public async Task MachRezept()
        {
            //Get the request
            var RSSRequest = WebRequest.Create("http://www.chefkoch.de/rss/rezept-des-tages.php");
            //Get the response
            var RSSResponse = await RSSRequest.GetResponseAsync();
            //Get the response content
            var RSSStream = new StreamReader(RSSResponse.GetResponseStream(), System.Text.Encoding.GetEncoding("ISO-8859-1"), true);
            //Read it!

            RSSContent.LoadXml(RSSStream.ReadToEnd());
            XmlNodeList items = RSSContent.GetElementsByTagName("item");
            foreach (var element in items)
            {
                Titel.Add((element as XmlElement).GetElementsByTagName("title").Item(0).InnerText);
                RezeptURLs.Add((element as XmlElement).GetElementsByTagName("link").Item(0).InnerText);
                Kurzbeschreibung.Add((element as XmlElement).GetElementsByTagName("description").Item(0).InnerText.Trim());
            }
            //URLs der Bilder, Zutaten, usw. aus den HTML-Dateien isolieren
            foreach (var element in RezeptURLs)
            {
                var HTMLRequest = WebRequest.Create(element);
                var HTMLResponse = await HTMLRequest.GetResponseAsync();
                var HTMLStream = new StreamReader(HTMLResponse.GetResponseStream(), System.Text.Encoding.GetEncoding("ISO-8859-1"), true);
                HTMLContent = HTMLStream.ReadToEnd();
                ImageURLs.Add(HTMLContent.Strip("<div id=\"slider\" class=\"nivoSlider\">", "</body>").Strip("<a href=\"", "\" id=\"0\""));
                Portionen.Add(Convert.ToInt32(HTMLContent.Strip("<span class=\"value-title\"  title=\"", "Portionen\"></span>")));
                Arbeitszeit.Add(HTMLContent.Strip("<strong>Arbeitszeit:</strong>", "<!-- Rich Snippet: Arbeitszeit im ISO-Format, unsichtbar als value-title (prepTime) -->").Trim());
                Ruhezeit.Add(HTMLContent.Strip("<strong>Ruhezeit:</strong>", "<!-- Schwierigkeitsgrad -->").Trim());
                Schwierigkeit.Add(HTMLContent.Strip("<strong>Schwierigkeitsgrad:</strong>", "<!-- Brennwert -->").Trim());
                Zubereitung.Add(HTMLContent.Strip("<div id=\"rezept-zubereitung\" class=\"instructions\">", "</div>").Replace("<br />", "\n").Trim());
                ZutatenExtraktor(HTMLContent);


            }
        }

        private void ZutatenExtraktor(string HTMLContent)
        {
            // Da pro Rezept mehrere Zutaten existieren, werden hier in jedem Durchgang unterlisten angelegt,
            // die letztendlich der Gesamtliste (der letzeten sieben Tage) hinzugefügt werden.
            List<string> Zutatenliste = new List<string>();
            List<double> Zutatenmengenliste = new List<double>();
            List<string> Zutateneinheitsliste = new List<string>();
            string Content = HTMLContent;
            string Zutaten_intermediate;
            string Zutateneinheit_intermediate;
            string Zutatenmenge_intermediate;
            while (Content.Contains("<tr class=\"ingredient\">"))
            {
                Content = Content.Insert(Content.Length, "<ENDE>");
                Zutatenmenge_intermediate = Content.Strip("<td class=\"amount\">", "&nbsp;").Trim();
                Zutateneinheit_intermediate = Content.Strip("&nbsp;", "</td>").Trim();
                Zutateneinheitsliste.Add(Zutateneinheit_intermediate);
                // Überprüfen, ob sich ein Bruch in der Mengenangabe befindet (1/2 Esslöffel...).
                if (Zutatenmenge_intermediate.Contains("<sub>"))
                {
                    Zutatenmenge_intermediate = Zutatenmenge_intermediate.Replace("</sup>/<sub>", "durch");
                    double a = Convert.ToDouble(Zutatenmenge_intermediate.Strip("<sup>", "durch"));
                    double b = Convert.ToDouble(Zutatenmenge_intermediate.Strip("durch", "</sub>"));
                    Zutatenmengenliste.Add(a / b);
                }
                // Überprüfen, ob die Mengenangabe fehlt.
                else if (Zutatenmenge_intermediate == "")
                    Zutatenmengenliste.Add(0);
                else
                {
                    Zutatenmengenliste.Add(Convert.ToDouble(Zutatenmenge_intermediate));
                }
                Zutaten_intermediate = Content.Strip("<td class=\"name\">", "</td>").Trim();
                if (Zutaten_intermediate.Contains("<a href=\""))
                {
                    Zutaten_intermediate = Zutaten_intermediate.Strip("target=\"_blank\">", "</a>").Trim();
                }
                Zutatenliste.Add(Zutaten_intermediate);
                Content = Content.Strip("<td class=\"name\">", "<ENDE>");
            }
            Zutaten.Add(Zutatenliste);
            Zutatenmenge.Add(Zutatenmengenliste);
            Zutateneinheit.Add(Zutateneinheitsliste);
        }
    }
}


namespace XTNs
{
    static class MyExtensions
    {
        // Extension, die den String nach "startstring" bis zum Beginn von "endstring" zurückgibt,
        // bzw. falls ersterer nicht existiert "N/A".
        public static string Strip(this string content, string startstring, string endstring)
        {
            int length = startstring.Length;
            if (!content.Contains(startstring))
                return "N/A";
            else
            {
                int start = content.IndexOf(startstring, 0);
                string intermediate = content.Substring(start + length, (content.Length - (start + length)));
                int stop = intermediate.IndexOf(endstring, 0);
                return intermediate.Remove(stop);
            }
        }
    }
}