using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace SchnittstelleImporter.XML2006
{
    /// <summary>
    /// 
    /// </summary>
    public static class XMLParser
    {
        /// <summary>
        /// 
        /// </summary>
        public static Dictionary<InspizierteAbwassertechnischeAnlage, string> anlageInFile = new Dictionary<InspizierteAbwassertechnischeAnlage, string>();
        /// <summary>
        /// Gibt eine Liste an anlagen zurück von einer XML Datei.
        /// </summary>
        /// <param name="xmldatei"></param>
        /// <returns></returns>
        public static List<InspizierteAbwassertechnischeAnlage> GetList(string xmldatei)
        {
            List<InspizierteAbwassertechnischeAnlage> result = new List<InspizierteAbwassertechnischeAnlage>();
            XmlDocument doc = new XmlDocument();
            doc.Load(xmldatei);
            XmlNode rootChild = doc.LastChild;

            XmlNamespaceManager manager = new XmlNamespaceManager(doc.NameTable);
            manager.AddNamespace("e", "http://www.ofd-hannover.la/Identifikation");
            XmlNode root = rootChild.SelectSingleNode("//e:Datenkollektive", manager);

            XmlNode zstdk = root.SelectSingleNode("//e:Zustandsdatenkollektiv", manager);
            XmlNodeList inspizierteDaten = zstdk.SelectNodes("//e:InspizierteAbwassertechnischeAnlage", manager);

            foreach (XmlNode node in inspizierteDaten)
            {
                InspizierteAbwassertechnischeAnlage anlage = GetAnlage(node);
                if (anlage == null) continue;
                result.Add(anlage);
                anlageInFile.Add(anlage, xmldatei);
            }
            return result;
        }
        private static InspizierteAbwassertechnischeAnlage GetAnlage(XmlNode xml)
        {
            XmlNode intOptischeInspektion = null;
            XmlNode intRohrleitung = null;
            XmlNode intRGrunddaten = null;
            XmlNode intInspektionsdaten = null;

            InspizierteAbwassertechnischeAnlage result = new InspizierteAbwassertechnischeAnlage();

            foreach (XmlNode d in xml.ChildNodes)
            {
                switch (d.Name)
                {
                    case "Objektbezeichnung":
                        result.Objektbezeichnung = d.InnerText;
                        break;
                    case "Anlagentyp":
                        result.Anlagentyp = (EAnlagetyp)Convert.ToInt32(d.InnerText);   //anlagentyp = Convert.ToInt32(d.InnerText);
                        break;
                    case "Lage":
                        //throw new NotImplementedException();
                        if (!d.HasChildNodes) break;
                        string strassename = "";
                        string ortname = "";
                        foreach (XmlNode _temp in d.ChildNodes)
                        {
                            switch (_temp.Name)
                            {
                                case "Strassenname": strassename = _temp.InnerText; break;
                                case "Ortsteilname": ortname = _temp.InnerText; break;
                                default: throw new NotImplementedException(_temp.Name);
                            }
                        }
                        result.Lage = new Lage(strassename, ortname);
                        break;
                    case "OptischeInspektion":
                        intOptischeInspektion = d;
                        break;

                }
            }

            if (intOptischeInspektion == null)
                throw new Exception("Es scheint was schief gelaufen zu sein, OptischeInspektion is null");

            string datum = "";
            string time = "";

            OptischeInspektion optischeInspektion = new OptischeInspektion();

            foreach (XmlNode d in intOptischeInspektion)
            {
                switch (d.Name)
                {
                    case "Inspektionsdatum":
                        datum = d.InnerText;
                        break;
                    case "Uhrzeit":
                        time = d.InnerText;
                        break;
                    case "Rohrleitung":
                        intRohrleitung = d;
                        break;
                }
            }
            string[] parseddatum = datum.Split('-');
            int year = Convert.ToInt32(parseddatum[0]);
            int month = Convert.ToInt32(parseddatum[1]);
            int day = Convert.ToInt32(parseddatum[2]);

            string[] parsedtime = time.Split(':');
            int hour = Convert.ToInt32(parsedtime[0]);
            int minute = Convert.ToInt32(parsedtime[1]);
            int second = Convert.ToInt32(parsedtime[2]);
            DateTime dt = new DateTime(year, month, day, hour, minute, second);

            optischeInspektion.Inspektionstime = dt;

            if (intRohrleitung == null)
                return null;
                //throw new NotImplementedException("Schaechte sind noch nicht implementiert");

            Rohrleitung rohr = new Rohrleitung();
            foreach (XmlNode d in intRohrleitung)
            {
                switch (d.Name)
                {
                    case "Rohrleitungstyp":
                        rohr.Rohrleitungstyp = (ERohrleitungstyp)Convert.ToInt32(d.InnerText);
                        break;
                    case "Inspektionslaenge":
                        rohr.Inspektionslaenge = Convert.ToDecimal(d.InnerText.Replace('.', ','));
                        break;
                    case "Inspektionsrichtung":
                        rohr.Inspektionsrichtung = d.InnerText;
                        break;
                    case "RGrunddaten":
                        intRGrunddaten = d;
                        break;
                    case "Inspektionsdaten":
                        intInspektionsdaten = d;
                        break;
                }
            }

            //List<RZustand> rzustand = ParseRZustand(intInspektionsdaten);

            rohr.Grunddaten = ParseGrundDaten(intRGrunddaten);
            rohr.Zustaende = ParseRZustand(intInspektionsdaten);
            optischeInspektion.Rohrleitung = rohr;
            result.OptischeInspektion = optischeInspektion;

            return result;
        }

        private static RGrunddaten ParseGrundDaten(XmlNode intRGrunddaten)
        {
            RGrunddaten grunddaten = new RGrunddaten();
            foreach (XmlNode d in intRGrunddaten.ChildNodes)
            {
                switch (d.Name)
                {
                    case "KnotenZulauf": grunddaten.KnotenZulauf = d.InnerText; break;
                    case "KnotenZulaufTyp": grunddaten.KnotenZulaufTyp = (EKnotenTyp)Convert.ToInt32(d.InnerText); break;
                    case "KnotenAblauf": grunddaten.KnotenAblauf = d.InnerText; break;
                    case "KnotenAblaufTyp": grunddaten.KnotenAblaufTyp = (EKnotenTyp)Convert.ToInt32(d.InnerText); break;
                    case "HerkunftProfilmasse": grunddaten.HerkunftProfilmasse = Convert.ToInt32(d.InnerText); break;
                    case "Profilhoehe": grunddaten.Profilhoehe = Convert.ToInt32(d.InnerText); break;
                    case "Profilbreite": grunddaten.Profilbreite = Convert.ToInt32(d.InnerText); break;
                    case "Profilart": grunddaten.Profilart = Convert.ToInt32(d.InnerText); break;
                    case "HerkunftMaterial": grunddaten.HerkunftMaterial = Convert.ToInt32(d.InnerText); break;
                    case "Material": grunddaten.Material = d.InnerText; break;
                    case "Regeleinzelrohrlaenge": grunddaten.Regeleinzelrohrlaenge = Convert.ToDecimal(d.InnerText.Replace('.', ',')); break;
                    case "ArtAuskleidung": grunddaten.ArtAuskleidung = Convert.ToInt32(d.InnerText); break;
                    case "Kanalart": grunddaten.Kanalart = d.InnerText; break;
                    case "Anschlussdaten": grunddaten.Anschlussddaten = ParseAnschlussdaten(d); break;
                    case "Innenschutz": grunddaten.Innenschutz = d.InnerText; break;
                    default: throw new NotImplementedException(d.Name);
                }
            }

            return grunddaten;
        }

        private static Anschlussdaten ParseAnschlussdaten(XmlNode anschlussdaten)
        {
            Anschlussdaten result = new Anschlussdaten();
            foreach (XmlNode d in anschlussdaten.ChildNodes)
            {
                switch (d.Name)
                {
                    case "Objektbezeichnung": result.Objektbezeichnung = d.InnerText; break;
                    case "Kantentyp": result.Kantentyp = (EKantenTyp)Convert.ToInt32(d.InnerText); break;
                    case "Entfernung": result.Entfernung = Convert.ToDecimal(d.InnerText.Replace('.', ',')); break;
                    case "Fixierung": result.Fixierung = d.InnerText; break;
                    default: Trace.WriteLine(d.Name); break;
                }
            }
            return result;
        }

        private static List<RZustand> ParseRZustand(XmlNode node)
        {
            List<RZustand> result = new List<RZustand>();

            foreach (XmlNode child in node.ChildNodes)
            {
                RZustand rZustand = new RZustand();
                foreach (XmlNode d in child.ChildNodes)
                {

                    switch (d.Name)
                    {
                        case "Station":
                            rZustand.Station = Convert.ToDecimal(d.InnerText.Replace('.', ','));
                            break;
                        case "InspektionsKode":
                            rZustand.Inspektionskode = d.InnerText;
                            break;
                        case "Charakterisierung1":
                            rZustand.Charakterisierung1 = d.InnerText;
                            break;
                        case "Charakterisierung2":
                            rZustand.Charakterisierung2 = d.InnerText;
                            break;
                        case "Verbindung":
                            rZustand.Verbindung = d.InnerText.Equals("0") ? false : true;
                            break;
                        case "PositionVon":
                            rZustand.PositionVon = Convert.ToInt32(d.InnerText);
                            break;
                        case "PositionBis":
                            rZustand.PositionBis = Convert.ToInt32(d.InnerText);
                            break;
                        case "Quantifizierung1Numerisch":
                            Quantifizierung quantifizierung1 = new Quantifizierung();
                            quantifizierung1.Numerisch = Convert.ToDecimal(d.InnerText.Replace('.', ','));
                            rZustand.Quantifizierung1 = quantifizierung1;
                            break;
                        case "Quantifizierung2Numerisch":
                            Quantifizierung quantifizierung2 = new Quantifizierung();
                            quantifizierung2.Numerisch = Convert.ToDecimal(d.InnerText.Replace('.', ','));
                            rZustand.Quantifizierung1 = quantifizierung2;
                            break;
                        case "Quantifizierung1Text":
                            Quantifizierung quantifizierung3 = new Quantifizierung();
                            quantifizierung3.Text = d.InnerText;
                            rZustand.Quantifizierung1 = quantifizierung3;
                            break;
                        case "Quantifizierung2Text":
                            Quantifizierung quantifizierung4 = new Quantifizierung();
                            quantifizierung4.Text = d.InnerText;
                            rZustand.Quantifizierung2 = quantifizierung4;
                            break;
                        case "Frame": break;
                        case "Klassifizierung": break;
                        case "Kommentar": rZustand.Kommentar = d.InnerText; break;
                        case "Streckenschaden": rZustand.Streckenschaden = d.InnerText; break;
                        case "StreckenschadenLfdNr": rZustand.Streckenschadennr = Convert.ToInt32(d.InnerText); break;
                        case "BezeichnungSanierung": break;
                        case "RVerfahrenSanierung": break;
                        case "Fotodatei": break;
                        case "FotoSpeichermedium": break;
                        case "Fotonummer": break;
                        case "Timecode": break;
                        case "GrundAbbruch": break;
                        default: throw new NotImplementedException(d.Name);

                    }
                }
                result.Add(rZustand);
            }


            return result;
        }
    }
}
