using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Pullenti.Npa.Documentory;
using System.Xml;
using Pullenti.Util;
using System.Threading;

namespace Pullenti.Documentory.WebServer
{
    public class DocWrap
    {
        public DocWrap(DocumentoryLocal d)
        {
            Doc = d;
            Doc.Modified += new EventHandler(Doc_Modified);
            Doc.DocLoaded += new EventHandler(Doc_DocLoaded);
            Doc.DocDeleted += new EventHandler(Doc_DocDeleted);
            Doc.EndOfLoaded += new EventHandler(Doc_EndOfLoaded);
        }

        void Doc_EndOfLoaded(object sender, EventArgs e)
        {
            OTyp = OperType.No;
        }

        void Doc_DocDeleted(object sender, EventArgs e)
        {
            ConsoleHelper.Write("\r\nRemove doc Id={0}", sender);
        }

        void Doc_DocLoaded(object sender, EventArgs e)
        {
            LoadingResult res = sender as LoadingResult; if (res == null) return;
            LastWrite = DateTime.Now;
            if (OTyp != OperType.ReloadAll)
                OTyp = OperType.LoadingDocs;
            ConsoleHelper.Write("\r\nLoad doc: {0}", res.ToString());
        }
        void Doc_Modified(object sender, EventArgs e)
        {
            LastWrite = DateTime.Now;
        }
        public override string ToString()
        {
            return Doc.Id;
        }
        public DocumentoryLocal Doc;
        public DateTime LastWrite;
        public OperType OTyp = OperType.No;
        public int OParam;

        public static void Save(List<DocWrap> list, string fileName)
        {
            using (XmlWriter xml = XmlWriter.Create(fileName, new XmlWriterSettings() { Indent = true, Encoding = System.Text.Encoding.UTF8 }))
            {
                xml.WriteStartDocument();
                xml.WriteStartElement("state");
                foreach (var d in list)
                {
                    xml.WriteStartElement("documentory");
                    xml.WriteAttributeString("id", d.Doc.Id);
                    if (d.LastWrite != DateTime.MinValue)
                        xml.WriteAttributeString("lastwrite", MiscHelper.OutDateTime(d.LastWrite));
                    if (d.OTyp != OperType.No)
                    {
                        xml.WriteAttributeString("operator", d.OTyp.ToString());
                        if (d.OParam > 0) xml.WriteAttributeString("param", d.OParam.ToString());
                    }
                    xml.WriteEndElement();
                }
                xml.WriteEndElement();
                xml.WriteEndDocument();
            }
        }

        public static void Load(List<DocWrap> list, string fname)
        {
            XmlDocument xml = new XmlDocument();
            xml.Load(fname);
            foreach (XmlNode x in xml.DocumentElement.ChildNodes)
            {
                try
                {
                    string id = x.Attributes["id"].Value;
                    foreach (var d in list)
                        if (d.Doc.Id == id)
                            foreach (XmlAttribute a in x.Attributes)
                                if (a.LocalName == "lastwrite")
                                {
                                    var dt = MiscHelper.TryParseDateTime(a.Value);
                                    if (dt != null) d.LastWrite = dt.Value;
                                }
                                else if (a.LocalName == "operator")
                                {
                                    try { d.OTyp = (OperType)Enum.Parse(typeof(OperType), a.Value, true); }
                                    catch { }
                                }
                                else if (a.LocalName == "param") d.OParam = int.Parse(a.Value);
                }
                catch { }
            }

        }

        public Thread ReindexThread;
        public void Reindex()
        {
            int max = Doc.InnerRepository.DocsMaxId;
            m_Stop = false;
            for (int id = OParam; id <= max; id++)
            {
                if (m_Stop) return;
                try
                {
                    byte[] body = Doc.InnerRepository.GetDocBody(id);
                    LoadingFile fi = new LoadingFile(null, body);
                    LoadingSubfile lsf = fi.GetFile(0);
                    LoadingDocument ldoc = lsf.CreateLoadingDocument();
                    Doc.LoadDocument(ldoc);
                    //Doc.ReloadDocument(id, null);
                    OParam = id + 1;
                    if ((id & 0x7F) == 0)
                        ConsoleHelper.WriteMemory(true);
                }
                catch (Exception ex)
                {
                    ConsoleHelper.Write("\r\nERROR (reload doc Id={0}): {1}", id, ex.ToString());
                }
            }
            OTyp = OperType.No;
            ReindexThread = null;
            try
            {
                Doc.InnerRepository.EndReindexAll();
            }
            catch (Exception ex)
            {
                ConsoleHelper.Write("\r\nERROR (EndReindexAll): {0}", ex.ToString());
            }
            if (ReindexOver != null)
                ReindexOver(this, EventArgs.Empty);
        }
        bool m_Stop;
        public void StopReindex()
        {
            try
            {
                m_Stop = true;
                for (int i = 0; i < 10; i++)
                {
                    if (!ReindexThread.IsAlive) break;
                    Thread.Sleep(1000);
                }
                if (ReindexThread != null && ReindexThread.IsAlive)
                    ReindexThread.Abort();
            }
            catch (Exception ex)
            {
            }
            ReindexThread = null;
            Doc.EndOfLoad();
        }
        public event EventHandler ReindexOver;
    }

    public enum OperType
    {
        No,
        ReloadAll,
        LoadingDocs
    }
}