using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Pullenti.Npa.Documentory;
using Pullenti.Util;
using System.IO;

namespace Pullenti.Documentory.WebServer
{
    // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
    // visit http://go.microsoft.com/?LinkId=9394801

    public class MvcApplication : System.Web.HttpApplication
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.IgnoreRoute("Rest");

            routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
            );

        }

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            RegisterRoutes(RouteTable.Routes);

            string baseDir = Server.MapPath("App_Data");
            if (baseDir.EndsWith("\\Service\\App_Data", StringComparison.OrdinalIgnoreCase))
                baseDir = Server.MapPath("..\\App_Data");
            AppDir = baseDir;
            ConsoleHelper.HideConsoleOutput = true;
            ConsoleHelper.CloseStreamAfterEachWrite = true;
            ConsoleHelper.LogDirectory = baseDir;
            ConsoleHelper.Clear(true);
            ConsoleHelper.Write("\r\nStart of work: {0}", DateTime.Now);
            ConsoleHelper.Write("\r\nOS System: {0} bit ", Environment.Is64BitOperatingSystem ? 64 : 32);
            Version = Pullenti.Npa.Constructor.ConstructorService.Version;
            ConsoleHelper.Write("\r\nSDK Version: {0}", Version);
            StartServer();
        }

        protected void Application_End()
        {
            StopServer();
            ConsoleHelper.Write("\r\nStop server: {0}", DateTime.Now);
        }

        public static DocumentoryMulti Doc;
        public static List<DocWrap> Locals = new List<DocWrap>();
        public static string Version;
        public static ServerStatus Status = ServerStatus.No;
        public static string AppDir;
        static object m_LockObj = new object();

        static public void LoadState()
        {
            string fname = Path.Combine(AppDir, "state.xml");
            try
            {
                if (File.Exists(fname))
                    DocWrap.Load(Locals, fname);
            }
            catch (Exception ex)
            { }
        }
        static public void SaveState()
        {
            string fname = Path.Combine(AppDir, "state.xml");
            try
            {
                DocWrap.Save(Locals, fname);
            }
            catch (Exception ex)
            {
            }
        }


        static public void StartServer()
        {
            lock (m_LockObj)
            {
                if (Doc != null) return;
                Status = ServerStatus.Starting;
                var doc = new DocumentoryMulti(); doc.EmbededIntoHttpServer = false;
                foreach (var d in Directory.GetDirectories(AppDir))
                {
                    try
                    {
                        DocumentoryLocal loc = new DocumentoryLocal(d, Path.GetFileName(d).ToUpper());
                        loc.Open(0);
                        Locals.Add(new DocWrap(loc));
                        doc.AddDocumentory(loc);
                        ConsoleHelper.Write("\r\nOpen '{0}': {1} docs", loc.Id, loc.DocumentsCount);
                    }
                    catch (Exception ex)
                    {
                        ConsoleHelper.Write("\r\nERROR on open '{0}': {1}", d, ex.ToString());
                    }
                }
                LoadState();
                foreach (var d in Locals)
                    if (d.OTyp == OperType.ReloadAll)
                        Reindex(d);
                Status = ServerStatus.Ok;
                Doc = doc;
            }
        }

        static public void StopServer()
        {
            lock (m_LockObj)
            {
                if (Doc == null) return;
                Status = ServerStatus.Stoping;

                // останавливаем потоки переиндексации
                foreach (var d in Locals)
                    if (d.ReindexThread != null)
                    {
                        d.StopReindex();
                        ConsoleHelper.Write("\r\nStop reindex {0}, pos = {1}, docs = {2}", d.Doc.Id, d.OParam, d.Doc.DocumentsCount);
                    }

                SaveState();
                var dr = Doc; Doc = null;
                ConsoleHelper.WriteMemory(false);
                ConsoleHelper.Write("\r\nClose documentories ", DateTime.Now);
                try
                {
                    if (dr != null)
                    {
                        dr.Dispose();
                        ConsoleHelper.Write(" OK");
                    }
                }
                catch (Exception ex)
                {
                    ConsoleHelper.Write("\r\nERROR: {0} ", ex.ToString());
                }

                ConsoleHelper.WriteMemory(true);
                Locals.Clear();
                Status = ServerStatus.Stoped;
            }
        }

        public static void Reindex(string id)
        {
            if(id != null)
                foreach(var d in Locals)
                    if (string.Compare(d.Doc.Id, id, true) == 0)
                    {
                        Reindex(d); return;
                    }
            foreach (var d in Locals)
                Reindex(d);
        }

        static void Reindex(DocWrap d)
        {
            if (d.ReindexThread != null) return;
            if (d.OTyp != OperType.ReloadAll)
            {
                d.OTyp = OperType.ReloadAll; d.OParam = 1;
                try
                {
                    d.Doc.InnerRepository.BeginReindexAll();
                }
                catch (Exception ex)
                {
                    ConsoleHelper.Write("\r\nERROR (BeginReindexAll): " + ex.ToString());
                }
            }
            d.ReindexThread = new System.Threading.Thread(d.Reindex);
            d.ReindexOver += new EventHandler(d_ReindexOver);
            d.ReindexThread.Start();
            ConsoleHelper.Write("\r\nStart reindex {0}, pos = {1}, docs = {2}", d.Doc.Id, d.OParam, d.Doc.DocumentsCount);
            SaveState();
        }

        static void d_ReindexOver(object sender, EventArgs e)
        {
            DocWrap d = sender as DocWrap; if (d == null) return;
            ConsoleHelper.Write("\r\nEnd reindex {0}, pos = {1}, docs = {2}", d.Doc.Id, d.OParam, d.Doc.DocumentsCount);
            SaveState();
        }
    }

    public enum ServerStatus
    {
        No,
        Starting,
        Ok,
        Stoping,
        Stoped
    }
}