using System;
using System.Linq;

namespace InABox.Core
{
    public enum ScriptType
    {
        None,
        BeforeQuery,
        AfterQuery,
        [Obsolete]
        AfterLoad,
        BeforeSave,
        AfterSave,
        BeforeDelete,
        AfterDelete,
        RowStyle
    }

    [UserTracking(false)]
    public class Script : Entity, IRemotable, IPersistent, ILicense<CoreLicense>
    {
        //[ComboLookupEditor(typeof(SectionLookups), Visible = Visible.Default)]
        [ComboLookupEditor(typeof(PropertyClassLookups))]
        [EditorSequence(1)]
        public string Section { get; set; }

        //private class SectionLookups : LookupGenerator
        //{
        //    public SectionLookups() : base()
        //    {                
        //        foreach (var entity in CoreUtils.Entities)
        //            this[entity.EntityName()()] = entity.EntityName()();
        //    }
        //}

        [EnumLookupEditor(typeof(ScriptType), Visible = Visible.Default)]
        [EditorSequence(2)]
        public ScriptType ScriptType { get; set; } = ScriptType.None;

        //[TextBoxEditor]
        //public String Name { get; set; }

        [ScriptEditor]
        [EditorSequence(3)]
        public string Code { get; set; } = "";

        private string NameSpace()
        {
            return string.IsNullOrWhiteSpace(Section) ? "" : string.Join(".", Section.Split('.').Reverse().Skip(1).Reverse());
        }

        private string EntityName()
        {
            return string.IsNullOrWhiteSpace(Section) ? "" : Section.Split('.').Last();
        }

        private string RowStyleTemplate()
        {
            return
                "using System;\r\n" +
                "using System.Collections.Generic;\r\n" +
                "using System.Linq;\r\n" +
                "using System.Runtime;\r\n" +
                "using System.Windows;\r\n" +
                "using System.Windows.Media;\r\n" +
                "using InABox.Core;\r\n" +
                "using Comal.Classes;\r\n" +
                "\r\n" +
                "public class Module\r\n" +
                "{\r\n" +
                "\r\n" +
                "    public CoreRow Row { get; set; }\r\n" +
                "    public String Column { get; set; }\r\n" +
                "\r\n" +
                "    public Brush Background { get; set; }\r\n" +
                "    public Brush Foreground { get; set; }\r\n" +
                "    public FontStyle Style { get; set; }\r\n" +
                "    public FontWeight Weight { get; set; }\r\n" +
                "\r\n" +
                "    public bool Execute()\r\n" +
                "    {\r\n" +
                "        return true;\r\n" +
                "    }\r\n" +
                "\r\n" +
                "}";
        }

        private string FilterTemplate()
        {
            return
                "using System;\r\n" +
                "using System.Collections.Generic;\r\n" +
                "using System.Linq;\r\n" +
                "using System.Runtime;\r\n" +
                "using InABox.Core;\r\n" +
                "using InABox.Database;\r\n" +
                "using InABox.Logging;\r\n" +
                "using " + NameSpace() + ";\r\n" +
                "\r\n" +
                "public class Module\r\n" +
                "{\r\n" +
                "\r\n" +
                "    public Store<" + EntityName() + "> Store { get; set; }\r\n" +
                "    public Filter<" + EntityName() + "> Filter { get; set; }\r\n" +
                "\r\n" +
                "    public bool Execute()\r\n" +
                "    {\r\n" +
                "        return true;\r\n" +
                "    }\r\n" +
                "\r\n" +
                "}";
        }

        private string CoreTableTemplate()
        {
            return
                "using System;\r\n" +
                "using System.Collections.Generic;\r\n" +
                "using System.Linq;\r\n" +
                "using System.Runtime;\r\n" +
                "using InABox.Core;\r\n" +
                "using InABox.Database;\r\n" +
                "using InABox.Logging;\r\n" +
                "using " + NameSpace() + ";\r\n" +
                "\r\n" +
                "public class Module\r\n" +
                "{\r\n" +
                "\r\n" +
                "    public Store<" + EntityName() + "> Store { get; set; }\r\n" +
                "    public CoreTable " + EntityName() + "s { get; set; }\r\n" +
                "\r\n" +
                "    public bool Execute()\r\n" +
                "    {\r\n" +
                "        foreach (CoreRow " + EntityName() + " in " + EntityName() + "s.Rows)\r\n" +
                "        {\r\n" +
                "        }\r\n" +
                "        return true;\r\n" +
                "    }\r\n" +
                "\r\n" +
                "}";
        }

        private string EntityTemplate()
        {
            return
                "using System;\r\n" +
                "using System.Collections.Generic;\r\n" +
                "using System.Linq;\r\n" +
                "using System.Runtime;\r\n" +
                "using InABox.Core;\r\n" +
                "using InABox.Database;\r\n" +
                "using InABox.Logging;\r\n" +
                "using " + NameSpace() + ";\r\n" +
                "\r\n" +
                "public class Module\r\n" +
                "{\r\n" +
                "\r\n" +
                "    public Store<" + EntityName() + "> Store { get; set; }\r\n" +
                "    public IEnumerable<" + EntityName() + "> " + EntityName() + "s { get; set; }\r\n" +
                "\r\n" +
                "    public bool Execute()\r\n" +
                "    {\r\n" +
                "        foreach (" + EntityName() + " " + EntityName() + " in " + EntityName() + "s)\r\n" +
                "        {\r\n" +
                "        }\r\n" +
                "        return true;\r\n" +
                "    }\r\n" +
                "\r\n" +
                "}";
        }

        private string GeneralTemplate()
        {
            return
                "using System;\r\n" +
                "using System.Collections.Generic;\r\n" +
                "using System.Linq;\r\n" +
                "using System.Runtime;\r\n" +
                "using InABox.Core;\r\n" +
                "using InABox.Database;\r\n" +
                "using InABox.Logging;" +
                "using " + NameSpace() + ";\r\n" +
                "\r\n" +
                "public class Module\r\n" +
                "{\r\n" +
                "\r\n" +
                "    public Object Data { get; set; }\r\n" +
                "\r\n" +
                "    public bool Execute()\r\n" +
                "    {\r\n" +
                "        throw new Exception(\"Not Implemented\");\r\n" +
                "        return true;\r\n" +
                "    }\r\n" +
                "\r\n" +
                "}";
        }

        private bool IsDefault(ScriptType type)
        {
            if (type.Equals(ScriptType.None))
                return string.IsNullOrWhiteSpace(Code);
            if (type.Equals(ScriptType.RowStyle))
                return Code.Equals(RowStyleTemplate());
            if (type.Equals(ScriptType.BeforeQuery))
                return Code.Equals(FilterTemplate());
            if (type.Equals(ScriptType.AfterQuery))
                return Code.Equals(CoreTableTemplate());
            if (type.Equals(ScriptType.AfterLoad))
                return Code.Equals(EntityTemplate());
            if (type.Equals(ScriptType.BeforeSave))
                return Code.Equals(EntityTemplate());
            if (type.Equals(ScriptType.AfterSave))
                return Code.Equals(EntityTemplate());
            if (type.Equals(ScriptType.BeforeDelete))
                return Code.Equals(EntityTemplate());
            if (type.Equals(ScriptType.AfterDelete))
                return Code.Equals(EntityTemplate());
            return Code.Equals(GeneralTemplate());
        }

        protected override void DoPropertyChanged(string name, object? before, object? after)
        {
            base.DoPropertyChanged(name, before, after);
            if (name.Equals("ScriptType") && IsDefault((ScriptType)before))
            {
                if (after == null || after.Equals(ScriptType.None))
                    Code = "";

                else if (after.Equals(ScriptType.RowStyle))
                    Code = RowStyleTemplate();

                else if (after.Equals(ScriptType.BeforeQuery))
                    Code = FilterTemplate();

                else if (after.Equals(ScriptType.AfterQuery))
                    Code = CoreTableTemplate();

                else if (after.Equals(ScriptType.AfterLoad)
                         || after.Equals(ScriptType.BeforeSave)
                         || after.Equals(ScriptType.AfterSave)
                         || after.Equals(ScriptType.BeforeDelete)
                         || after.Equals(ScriptType.AfterDelete))
                    Code = EntityTemplate();

                else
                    Code = GeneralTemplate();
            }
        }
    }
}