using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Mime;
using System.Text;
using System.Xml.Linq;

using BS.Shared.Core;

namespace BeWo.Data.ICD10
{
    public static class ICD10DAO
    {
        private static readonly Dictionary<string, string> _Codes2Diagnosis;

        private static readonly Dictionary<string, string> test;

        private static readonly XDocument _File;

        private static readonly Dictionary<string, List<Dictionary<string, string>>> aussen = new Dictionary<string, List<Dictionary<string, string>>>();

        static ICD10DAO()
        {
            try
            {
                var s = DateTime.Now;

                //_File = XDocument.Load(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"bin\ICD10\icd10gm2009syst_claml_20080929.xml"));
				//_File = XDocument.Load(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"bin\ICD10\icd10gm2012syst_claml_20110923.xml"));
				string file = ConfigurationManager.AppSettings.Get("ICD10File");
	            if (String.IsNullOrEmpty(file) ||
	                !File.Exists(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"bin\ICD10\" + file)))
	            {
		            file = "icd10.xml";
	            }
				file = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"bin\ICD10\" + file);
	            _File = XDocument.Load(file);
				
				

	            var classes = _File.Root.Descendants("Class").Where(n => n.Attribute("kind").Value.Equals("category"));

	            var modifier2ModifierClasses = new Dictionary<String, IList<XElement>>();
				foreach (var mc in _File.Root.Descendants("ModifierClass"))
				{
					String code = mc.Attribute("modifier").Value;
					
					if (!String.IsNullOrEmpty(code))
					{
						IList<XElement> elements = null;
						if (!modifier2ModifierClasses.ContainsKey(code))
						{
							elements = new List<XElement>();
							modifier2ModifierClasses.Add(code, elements);
						}
						else
						{
							elements = modifier2ModifierClasses[code];
						}
						elements.Add(mc);
					}
					
				}
				
				_Codes2Diagnosis = new Dictionary<string, string>();

	            foreach (var c in classes)
	            {
		            String classCode = c.Attribute("code").Value;
		            var diagnosis = c.Descendants()
				            .Single(m => m.Attribute("kind") != null && m.Attribute("kind").Value.Equals("preferred"))
				            .Descendants().First().Value;

					_Codes2Diagnosis.Add(classCode, diagnosis);
		            var modifiedBy = c.Descendants("ModifiedBy").FirstOrDefault();
		            if (modifiedBy != null)
		            {
			            String code = modifiedBy.Attribute("code").Value;

			            if (modifier2ModifierClasses.ContainsKey(code))
			            {
				            var modifierList = modifier2ModifierClasses[code];
				            foreach (var xElement in modifierList)
				            {
								String modifierCode = xElement.Attribute("code").Value;
								var modifiedDiagnosis = xElement.Descendants()
									.Single(m => m.Attribute("kind") != null && m.Attribute("kind").Value.Equals("preferred"))
									.Descendants().First().Value;

								_Codes2Diagnosis.Add(classCode + modifierCode, diagnosis + ": " + modifiedDiagnosis);
				            }
			            }
		            }

					
	            }
                //_Codes2Diagnosis = _File.Root.Descendants("Class").Where(n => n.Attribute("kind").Value.Equals("category"))
                //    .ToDictionary(n => n.Attribute("code").Value, n => n.Descendants().Single(m => m.Attribute("kind") != null && m.Attribute("kind").Value.Equals("preferred")).Descendants().First().Value);

                try
                {
					// Codes ohne Punkt kann man ignorieren
					// E10.2 "Mit Nierenkomplikationen" -> .2 = code, "Mit Nierenkomplikationen" = val
					// Zusammenhang (E10, E11 etc.) über ModifiedBy der Class in _Codes2Diagnosis
					// ModifiedBy ist der Modifier in ModifierClass
                    var modifierClasses = _File.Root.Descendants("ModifierClass").ToList();

					foreach (var modifierClass in modifierClasses)
                    {
						var modifier = modifierClass.Attribute("modifier").Value;
						var code = modifierClass.Attribute("code").Value;

                        if (!code.StartsWith("."))
                            continue;

						var val = modifierClass.Descendants().Single(m => m.Attribute("kind") != null && m.Attribute("kind").Value.Equals("preferred")).Descendants().First().Value;

                        var innen = new Dictionary<string, string> { { code, val } };
                        if (aussen.ContainsKey(modifier))
                        {
                            aussen[modifier].Add(innen);
                        }
                        else
                        {
                            aussen.Add(modifier, new List<Dictionary<string, string>> {innen});
                        }
                    }
                }
                catch (Exception ex)
                {
                    
                }

                var e = DateTime.Now - s;
            }
            catch (Exception)
            {

            }
        }

        public static string GetCompressedString()
        {
            var sr = new StringBuilder();

            if(_Codes2Diagnosis != null)
            {
                foreach (var kvp in _Codes2Diagnosis)
                {
                    sr.AppendLine(kvp.Key + ";" + kvp.Value);
                }
            }

            return Utils.Compress(sr.ToString());
        }

        public static string GetDiagnosisForCode(string code)
        {
            while ((code = code.Replace(" ", string.Empty)).Contains(" "))
            {
                ;
            }

            if (_Codes2Diagnosis.ContainsKey(code))
            {
                return _Codes2Diagnosis[code];
            }

            return null;
        }
    }
}