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

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

        private string path;
        
        private List<Page> pages;

        public string FileName { get; set; }

        public string Status { get; set; }

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

            GC.SuppressFinalize(this);
        }

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

        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 path, List<Page> pages) : this(path)
        {
            this.pages = pages;
        }

        public Document(string xmlPath, bool encrypted = true)
        {
            this.path = xmlPath;
            this.FileName = System.IO.Path.GetFileNameWithoutExtension(xmlPath);
            this.Load(xmlPath, MAINTAG, encrypted ? true : false, encrypted);

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

            this.Status = root.Attributes[@"Status"]?.Value ?? string.Empty;

            this.pages = new List<Page>();
            foreach (XmlElement xmlPage in this.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();

            if (root.Attributes[@"Status"] == null)
                ((XmlElement)root).SetAttribute(@"Status", Status);
            else
                root.Attributes[@"Status"].Value = Status;

            this.pages.OrderBy(page => page.Index).ToList().ForEach(page =>
            {
                root.AppendChild(page.Export(this));
            });

            this.AppendChild(root);

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

        public void Save(bool encripty = true, bool hide = true)
        {
            string current = System.DateTime.Now.ToString();
            this.AppendChild(this.CreateXmlDeclaration("1.0", @"UTF-8", @"yes"));

            XmlElement root = this.CreateElement(MAINTAG);

            this.pages.OrderBy(page => page.Index).ToList().ForEach(page =>
            {
                root.AppendChild(page.Export(this));
            });

            this.AppendChild(root);

            base.Save(this.path, MAINTAG, encripty, hide);
        }
        
        public Document Copy() => new Document(path, Pages.Select(p => p.Clone()).ToList());
    }
}
