// Created with MonoDevelop
//
//    QuickStep: Acquire, view and identify spectra 
//    Copyright (C) 2022, Hiperscan GmbH Dresden, Germany
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.

using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;

using Hiperscan.Unix;

namespace Hiperscan.ApoIdentCommon.ApoConfig.IO
{
    public class EntryWriter<T> : SecureFileWriter
    {
        public EntryWriter() : base()
        {
        }

        public EntryWriter(string file_name, int repeats = 5) : base(file_name, repeats)
        {
        }

        protected override void Read(string file_name)
        {
            XmlDocument doc = new XmlDocument();
            using (StreamReader sr = new StreamReader(file_name, System.Text.Encoding.UTF8))
            {
                doc.Load(sr);
            }

            XmlNode root = doc.DocumentElement;

            XmlNodeList entry_nodes = root.SelectNodes(this.EntryTagName);
            if (entry_nodes != null && entry_nodes.Count > 0)
            {
                foreach (XmlNode entry_node in entry_nodes)
                {
                    string id = null;
                    if (entry_node.Attributes[this.IdAttributeName] != null)
                        id = entry_node.Attributes[this.IdAttributeName].Value;

                    if (String.IsNullOrEmpty(id) == true)
                        continue;

                    if (String.IsNullOrEmpty(entry_node.InnerText) == true)
                        continue;

                    this.Entries.Add(id, entry_node.InnerText);
                }
            }
        }

        protected override void Write(string file_name)
        {
            XmlDocument doc = new XmlDocument();

            doc.LoadXml(String.Format("<{0}></{0}>", this.RootNodeName));
            XmlNode root = doc.DocumentElement;

            foreach (string id in this.Entries.Keys)
            {
                XmlNode entry_element = doc.CreateElement(this.EntryTagName);
                entry_element.InnerText = this.Entries[id].ToString();
                root.AppendChild(entry_element);

                XmlAttribute id_attribute = doc.CreateAttribute(this.IdAttributeName);
                id_attribute.Value = id;
                entry_element.Attributes.Append(id_attribute);
            }

            FileIO.Save(doc, file_name);
        }

        public override void Clear()
        {
            this.Entries.Clear();
        }

        public bool ContainsKey(string key)
        {
            return this.Entries.ContainsKey(key);
        }

        public void AddValue(string key, string value)
        {
            if (this.ContainsKey(key) == false)
                this.Entries.Add(key, String.Empty);
                
            this.Entries[key] = value;
        }

        public string RemoveValue(string key)
        {
            string value = this.Entries[key];
            this.Entries.Remove(key);
            return value;
        }

        public string GetValue(string key)
        {
            return this.Entries[key];
        }

        public override bool HasWritingData
        {
            get
            {
                return this.Entries.Count > 0;
            }
        }

        public string RootNodeName => typeof(T).Name;
        public string IdAttributeName => "Id";
        public string EntryTagName => "CompletionEntry";

        protected Dictionary<string, string> Entries { get; set; } = new Dictionary<string, string>();
    }
}
