using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using System.Xml.Linq;

namespace ZionVault.Binder.Verified
{
    public class Document : ZionVault.Util.Xml, IDisposable
    {
        private const string MAINTAG = @"Document";

        private string fileName;

        private string path;

        private string type;

        private List<Page> pages;

        private string option;

        private string status;

        public void Dispose()
        {
            if (this.pages != null)
                foreach (Page p in pages)
                    p.Dispose();

            GC.SuppressFinalize(this);
        }

        public string FileName { get => fileName; set => fileName = value; }

        public string Type { get => type; set => type = value; }

        public List<Page> Pages { get => this.pages; }

        public string Option { get => option; set => option = value; }

        public string Status { get => status; set => status = value; }

        public List<Field> AllFields
        {
            get
            {
                List<Field> fields = new List<Field>();

                pages.ForEach(page =>
                {
                    fields.AddRange(page.SearchElements.Select(f => f.Clone()).ToList());
                });

                return fields;
            }
        }
        public List<Field> GetFieldsAtPage(int page)
        {
            return this.pages[page].SearchElements.Select(f => f.Clone()).ToList();
        }

        public Document()
        {
            this.pages = new List<Page>();
        }

        public Document(string xmlPath, bool encrypted = true)
        {
            if (!System.IO.File.Exists(xmlPath)) {
                this.pages = new List<Page>();
                return;
            }

            this.path = xmlPath;
            Util.Xml xml = new Util.Xml();
            xml.Load(xmlPath, MAINTAG, encrypted ? true : false, encrypted);

            this.fileName = xml.SelectSingleNode(MAINTAG).Attributes[@"FileName"]?.Value ?? null;

            this.type = xml.SelectSingleNode(MAINTAG).Attributes[@"Type"]?.Value ?? null;

            this.option = xml.SelectSingleNode(MAINTAG).Attributes[@"Option"]?.Value ?? null;

            this.status = xml.SelectSingleNode(MAINTAG).Attributes[@"Status"]?.Value ?? string.Empty;

            this.pages = new List<Page>();
            foreach (XmlElement xmlPage in xml.GetElementsByTagName(@"page"))
            {
                this.pages.Add(new Page(xmlPage));
            }
        }
        public void Save(string path, bool encripty = true, bool hide = true)
        {
            string current = System.DateTime.Now.ToString();
            try
            {
                this.AppendChild(this.CreateXmlDeclaration("1.0", @"UTF-8", @"yes"));
            }
            catch { }

            XmlNode root =
                this.GetElementsByTagName(MAINTAG).Item(0) ??
                this.CreateElement(MAINTAG);

            root.RemoveAll();

            pages.GroupBy(p => new { p.Index, p } ).Select(page => page.First()).ToList()
                .ForEach(page =>
            {
                root.AppendChild(page.Export(this));
            });

            if (this.GetElementsByTagName(MAINTAG).Count == 0)
            {
                this.AppendChild(root);
            }

            base.Save(path, MAINTAG, encripty, hide);
        }
    }
}
