using Microsoft.Win32.SafeHandles;
using SewerStammGen.Shared.Contracts;
using SewerStammGen.Shared.Domain;
using SewerStammGen.Shared.Enum;
using Shared.Contracts;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;


// TODO: Admindaten fehlen

// TODO: Datenkollektive fehlen Datenstatus und Erstellungsdatum
//       Stammdatenkollektiv auszufüllen
/*
Stammdatenkollektiv fehlt: GeoObjektart unter Geometrie


*/
namespace WWTech_KanalSchnittstelle.Exporter.XML
{
    public class XML2013 : IExport
    {
        private XmlDocument _file;
        private List<Schacht> _schaechte;
        private List<Kanal> _haltungen;

        private static Dictionary<EExportType, Tuple<string, string>> ExportVersionen = new Dictionary<EExportType, Tuple<string, string>>()
        {
            { EExportType.XML2006, new Tuple<string, string>("2006-10","2") },
            { EExportType.XML2013, new Tuple<string, string>("2013-02","5") },
            { EExportType.XML2017, new Tuple<string, string>("2017-07","6") }
        };

        public async Task<bool> Export(string projektname, EKodierungssystem kodierungssystem,List<Kanal> haltungen, List<Schacht> schaechte, IWWLog logger)
        {
            _schaechte = schaechte;
            _haltungen = haltungen;
            _file = new XmlDocument();
            XmlDeclaration newChild = _file.CreateXmlDeclaration("1.0", "ISO-8859-1", "yes");
            _file.AppendChild(newChild);
            XmlElement xmlElement = CreateElementFor("Identifikation", _file);
            xmlElement.SetAttribute("xmlns", "http://www.ofd-hannover.la/Identifikation");
            XmlElement xmlElement2 = CreateElementFor("Version", xmlElement);
            xmlElement2.InnerText = ExportVersionen[EExportType.XML2013].Item1; // XML Version 
            
            DoAdmindata(xmlElement);
            DoCollectives(xmlElement);

            _file.Save(projektname + ".xml");
            return true;
        }

        private XmlElement CreateElementFor(string name, XmlNode parentElement)
        {
            XmlElement xmlElement = _file.CreateElement(name);
            parentElement.AppendChild(xmlElement);
            return xmlElement;
        }

        private void DoAdmindata(XmlElement idElement)
        {
            XmlElement parentElement = CreateElementFor("Admindaten", idElement);
            XmlElement Liegenschaft = CreateElementFor("Liegenschaft", parentElement);
            DoRowValue(Liegenschaft, "Liegenschaftsnummer", "0");
            DoRowValue(Liegenschaft, "Objektnummer", "0");
            DoRowValue(Liegenschaft, "Liegenschaftsbezeichnung", "0");
            DoRowValue(Liegenschaft, "Liegenschaftsort", "0");
            DoRowValue(Liegenschaft, "Liegenschaftsnutzung", "komunal");

            XmlElement Verwaltung = CreateElementFor("Verwaltung", parentElement);
            DoRowValue(Verwaltung, "DienststelleVerwaltend", "123");
            DoRowValue(Verwaltung, "DienststelleHausverwaltend", "123");
            DoRowValue(Verwaltung, "DienststelleBauaufsicht", "123");
            DoRowValue(Verwaltung, "DienststelleBaudurchfuehrung", "123");
            DoRowValue(Verwaltung, "NummerDienststelleBaudurchfuehrung", "123");
            DoRowValue(Verwaltung, "Zustaendigkeitsbereich", "123");
            DoRowValue(Verwaltung, "Aktenzeichen", "123");
            DoRowValue(Verwaltung, "Abwasserbeseitigungspflicht", "1");
            DoRowValue(Verwaltung, "Wasserbehoerde", "123");
        }

        private void DoCollectives(XmlElement idElement)
        {
            XmlElement dataCollectiveElement = DoRow(idElement, "Datenkollektive");
            DoRowValue(dataCollectiveElement, "Datenstatus", "1");
            DoRowValue(dataCollectiveElement, "Erstellungsdatum", "2023-07-25");
            DoCollectives1Labels(dataCollectiveElement);
            DoCollectives2Base(dataCollectiveElement);
        }

        private void DoCollectives2Base(XmlElement dataCollectiveElement)
        {
            XmlElement parentElement = DoRow(dataCollectiveElement, "Stammdatenkollektiv");

            foreach (Kanal haltung in _haltungen)
            {
                XmlElement xmlElement = DoHaltungRow(haltung, parentElement, "AbwassertechnischeAnlage");
            }

            foreach (Schacht schacht in _schaechte)
            {
                XmlElement xmlElement = DoSchachtRow(schacht, parentElement, "AbwassertechnischeAnlage");
            }
        }

        private XmlElement DoSchachtRow(Schacht schacht, XmlElement parentElement, string originTableName)
        {
            XmlElement xmlElement = null;
            xmlElement = _file.CreateElement(originTableName);
            parentElement.AppendChild(xmlElement);

            DoRowValue(xmlElement, "Objektbezeichnung", schacht.Objektbezeichnung);
            DoRowValue(xmlElement, "Objektart", "2");
            DoRowValue(xmlElement, "Entwaesserungsart", schacht.Entwaesserung == EEntwaeserung.Regenwasser ? "KR" : schacht.Entwaesserung == EEntwaeserung.Schmutzwasser ? "KS" : "KM");

            XmlElement xmlElement1 = CreateElementFor("Knoten", xmlElement);
            DoRowValue(xmlElement1, "KnotenTyp", "0");

            XmlElement xmlElement2 = CreateElementFor("Schacht", xmlElement1);
            DoRowValue(xmlElement2, "SchachtFunktion", "1");

            XmlElement GeometrieElement = CreateElementFor("Geometrie", xmlElement);
            XmlElement GeometrieDaten = CreateElementFor("Geometriedaten", GeometrieElement);
            XmlElement KnotenElement = CreateElementFor("Knoten", GeometrieDaten);
            XmlElement PunktElement = CreateElementFor("Punkt", KnotenElement);
            DoRowValue(PunktElement, "Rechtswert", schacht.SohlRechtsWert.ToString().Replace(',', '.'));
            DoRowValue(PunktElement, "Hochwert", schacht.SohlHochWert.ToString().Replace(',', '.'));
            DoRowValue(PunktElement, "Punkthoehe", schacht.SohlHoehe.ToString().Replace(',', '.'));
            DoRowValue(PunktElement, "PunktattributAbwasser", "SMP");
            PunktElement = CreateElementFor("Punkt", KnotenElement);
            if(schacht.DeckelRechtsWert != 0) DoRowValue(PunktElement, "Rechtswert", schacht.DeckelRechtsWert.ToString().Replace(',', '.'));
            if(schacht.DeckelHochWert != 0) DoRowValue(PunktElement, "Hochwert", schacht.DeckelHochWert.ToString().Replace(',', '.'));
            DoRowValue(PunktElement, "Punkthoehe", schacht.DeckelHoehe.ToString().Replace(',', '.'));
            DoRowValue(PunktElement, "PunktattributAbwasser", "DMP");
            return xmlElement;
        }

        private XmlElement DoHaltungRow(Kanal haltung, XmlElement parentElement, string orginalTableName)
        {
            XmlElement xmlElement = null;
            xmlElement = _file.CreateElement(orginalTableName);
            parentElement.AppendChild(xmlElement);

            DoRowValue(xmlElement, "Objektbezeichnung", haltung.Objektbezeichnung);
            DoRowValue(xmlElement, "Objektart", "1");
            DoRowValue(xmlElement, "Entwaesserungsart", haltung.Entwaesserung == EEntwaeserung.Regenwasser ? "KR" : haltung.Entwaesserung == EEntwaeserung.Schmutzwasser ? "KS" : "KM");

            XmlElement xmlElement1 = CreateElementFor("Kante", xmlElement);
            DoRowValue(xmlElement1, "KantenTyp", "0");
            DoRowValue(xmlElement1, "KnotenZulauf", haltung.StartSchacht.Objektbezeichnung);
            DoRowValue(xmlElement1, "KnotenZulaufTyp", "0");
            DoRowValue(xmlElement1, "KnotenAblauf", haltung.EndSchacht.Objektbezeichnung);
            DoRowValue(xmlElement1, "KnotenAblaufTyp", "0");
            DoRowValue(xmlElement1, "Material", haltung.Material);

            XmlElement xmlElement2 = CreateElementFor("Profil", xmlElement1);
            DoRowValue(xmlElement2, "SonderprofilVorhanden", "0");
            DoRowValue(xmlElement2, "Profilart", "0");
            DoRowValue(xmlElement2, "Profilbreite", haltung.DN.ToString());
            DoRowValue(xmlElement2, "Profilhoehe", haltung.DN.ToString());

            xmlElement2 = CreateElementFor("Haltung", xmlElement1);
            DoRowValue(xmlElement2, "HaltungsFunktion", "1");
            DoRowValue(xmlElement2, "DMPLaenge", haltung.Haltungslaenge.ToString().Replace(',', '.'));

            xmlElement1 = CreateElementFor("Lage", xmlElement);

            xmlElement1 = CreateElementFor("Geometrie", xmlElement);

            DoRowValue(xmlElement1, "GeoObjekttyp", "L");
            xmlElement2 = CreateElementFor("Geometriedaten", xmlElement1);
            XmlElement xmlElement3 = CreateElementFor("Kanten", xmlElement2);
            XmlElement xmlElement4 = CreateElementFor("Kante", xmlElement3);

            XmlElement xmlElement5 = CreateElementFor("Start", xmlElement4);
            DoRowValue(xmlElement5, "Rechtswert", haltung.StartSchacht.SohlRechtsWert.ToString().Replace(',', '.'));
            DoRowValue(xmlElement5, "Hochwert", haltung.StartSchacht.SohlHochWert.ToString().Replace(',', '.'));
            DoRowValue(xmlElement5, "Punkthoehe", haltung.StartSchacht.SohlHoehe.ToString().Replace(',', '.'));
            DoRowValue(xmlElement5, "PunktattributAbwasser", "SMP");

            xmlElement5 = CreateElementFor("Ende", xmlElement4);
            DoRowValue(xmlElement5, "Rechtswert", haltung.EndSchacht.SohlRechtsWert.ToString().Replace(',', '.'));
            DoRowValue(xmlElement5, "Hochwert", haltung.EndSchacht.SohlHochWert.ToString().Replace(',', '.'));
            DoRowValue(xmlElement5, "Punkthoehe", haltung.EndSchacht.SohlHoehe.ToString().Replace(',', '.'));
            DoRowValue(xmlElement5, "PunktattributAbwasser", "SMP");


            return xmlElement;
        }

        private XmlElement DoRow(XmlElement parentElement, string originTableName)
        {
            XmlElement xmlElement = null;
            xmlElement = _file.CreateElement(originTableName);
            parentElement.AppendChild(xmlElement);
            return xmlElement;
        }

        private void DoCollectives1Labels(XmlElement dataCollectiveElement)
        {
            XmlElement parentElement = CreateElementFor("Kennungen", dataCollectiveElement);
            XmlElement xmlElement = CreateElementFor("Kollektiv", parentElement);
            DoRowValue(xmlElement, "Kennung", "STA01");
            DoRowValue(xmlElement, "Kollektivart", "1");
            XmlElement parentElement2 = CreateElementFor("Kollektiveigenschaft", xmlElement);
            XmlElement parentElement3 = CreateElementFor("Stammdaten", parentElement2);
            DoRowValue(parentElement3, "Stammdatentyp", "1");
            DoRowValue(parentElement3, "Bautechnik", "1");
            DoRowValue(parentElement3, "Geometrie", "1");
            DoRowValue(parentElement3, "Sanierung", "0");
            DoRowValue(parentElement3, "Umfeld", "0");

            //DoRow(parentElement2, "Zustandsdaten");
            //DoRow(parentElement2, "Hydraulikdaten");
            //DoRow(parentElement2, "Betriebsdaten");
            DoRowValue(xmlElement, "Regelwerk", ExportVersionen[EExportType.XML2013].Item2);
            DoRowValue(xmlElement, "Bearbeitungsstand", "2");
            DoRowValue(xmlElement, "Kommentar", "test");
        }

        private XmlElement DoRowValue(XmlElement rowElement, string originColName, string value)
        {
            XmlElement xmlElement = CreateElementFor(originColName, rowElement);
            if (value != "")
            {
                xmlElement.InnerText = value;
            }
            return xmlElement;
        }
    }
}
