using LiteDB;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VIZ.Package.Domain;
using VIZ.Package.Storage;

namespace VIZ.Package.Service
{
    /// <summary>
    /// 控制对象服务
    /// </summary>
    public class ControlObjectService
    {
        /// <summary>
        /// 保存控制字段
        /// </summary>
        /// <param name="pageBase">页或模板</param>
        /// <param name="fields">控制字段</param>
        public void SaveControlFields(PageModelBase pageBase, IList<ControlFieldNodeModel> fields)
        {
            Guid id = this.GetTemplateIdOrPageId(pageBase);

            this.SaveControlFields(id, fields);
        }

        /// <summary>
        /// 保存控制字段
        /// </summary>
        /// <param name="id">页或模板ID</param>
        /// <param name="fields">控制字段</param>
        public void SaveControlFields(Guid id, IList<ControlFieldNodeModel> fields)
        {
            ApplicationDomainEx.ProjectDbContext.ControlField.DeleteMany(p => p.PageID == id);

            List<ControlFieldEntity> list = new List<ControlFieldEntity>();
            foreach (ControlFieldNodeModel field in fields)
            {
                ControlFieldEntity entity = new ControlFieldEntity();
                entity.PageID = id;
                entity.FieldIdentifier = field.FieldIdentifier;
                entity.Value = field.Value;
                entity.Type = field.Type;
                entity.FieldDetail = field.FieldDetail;
                entity.IsCustom = field.IsCustom;

                list.Add(entity);
            }

            ApplicationDomainEx.ProjectDbContext.ControlField.Insert(list);
        }

        /// <summary>
        /// 拷贝控制字段
        /// </summary>
        /// <param name="srcID">源ID</param>
        /// <param name="dstID">目标ID</param>
        public void CopyControlFields(Guid srcID, Guid dstID)
        {
            var src = ApplicationDomainEx.ProjectDbContext.ControlField.Find(p => p.PageID == srcID).ToList();
            ApplicationDomainEx.ProjectDbContext.ControlField.DeleteMany(p => p.PageID == dstID);
            src.ForEach(p =>
            {
                p.Id = 0;
                p.PageID = dstID;
            });
            ApplicationDomainEx.ProjectDbContext.ControlField.Insert(src);
        }

        /// <summary>
        /// 获取控制字段
        /// </summary>
        /// <param name="pageBase">页或模板</param>
        /// <returns>控制字段</returns>
        public List<ControlFieldEntity> GetControlFields(PageModelBase pageBase)
        {
            Guid id = this.GetTemplateIdOrPageId(pageBase);

            var result = ApplicationDomainEx.ProjectDbContext.ControlField.Find(p => p.PageID == id);

            return result.ToList();
        }

        /// <summary>
        /// 更新控制字段值
        /// </summary>
        /// <param name="models">模型</param>
        /// <param name="entitys">实体</param>
        public void UpdateControlFieldValue(IList<ControlFieldNodeModel> models, IList<ControlFieldEntity> entitys)
        {
            Dictionary<string, ControlFieldEntity> dic = entitys.ToDictionary(p => p.FieldIdentifier, p => p);

            foreach (ControlFieldNodeModel model in models)
            {
                if (!dic.TryGetValue(model.FieldIdentifier, out ControlFieldEntity entity))
                    continue;

                if (model.Type != entity.Type)
                    continue;

                model.Value = entity.Value;
            }
        }

        /// <summary>
        /// 保存控制对象
        /// </summary>
        /// <param name="pageBase">页或模板</param>
        /// <param name="obj">控制对象</param>
        /// <remarks>
        /// 目前每个页只保留主控制对象
        /// </remarks>
        public void SaveControlObject(PageModelBase pageBase, ControlObjectModel obj)
        {
            Guid id = this.GetTemplateIdOrPageId(pageBase);

            ControlObjectEntity entity = ApplicationDomainEx.ProjectDbContext.ControlObject.FindOne(p => p.PageID == id);
            entity = entity ?? new ControlObjectEntity();

            entity.PageID = id;
            entity.TreeNodeName = obj.TreeNodeName;
            entity.TreeNodePath = obj.TreeNodePath;
            entity.Description = obj.Description;
            entity.FieldDetails = obj.FieldDetails;
            entity.CustomFieldDetails = obj.CustomFieldDetails;
            entity.UseAllDirectors = obj.UseAllDirectors;
            entity.TransitionLogic = obj.TransitionLogic;
            entity.LayerIdentifier = obj.LayerIdentifier;
            entity.StateIdentifier = obj.StateIdentifier;
            entity.BackgroundScene = obj.BackgroundScene;

            ApplicationDomainEx.ProjectDbContext.ControlObject.Upsert(entity);
        }

        /// <summary>
        /// 拷贝控制对象
        /// </summary>
        /// <param name="srcID">源ID</param>
        /// <param name="dstID">目标ID</param>
        public void CopyControlObjects(Guid srcID, Guid dstID)
        {
            var src = ApplicationDomainEx.ProjectDbContext.ControlObject.Find(p => p.PageID == srcID).ToList();
            src.ForEach(p =>
            {
                p.Id = 0;
                p.PageID = dstID;
            });
            ApplicationDomainEx.ProjectDbContext.ControlObject.DeleteMany(p => p.PageID == dstID);
            ApplicationDomainEx.ProjectDbContext.ControlObject.Insert(src);
        }

        /// <summary>
        /// 获取控制对象
        /// </summary>
        /// <param name="pageBase">页基类</param>
        /// <returns>控制对象</returns>
        public List<ControlObjectEntity> GetControlObject(PageModelBase pageBase)
        {
            Guid id = this.GetTemplateIdOrPageId(pageBase);

            var result = ApplicationDomainEx.ProjectDbContext.ControlObject.Find(p => p.PageID == id).ToList();

            return result;
        }

        /// <summary>
        /// 获取模板ID或页ID
        /// </summary>
        /// <param name="pageBase">页基类</param>
        /// <returns>模板ID或页ID</returns>
        private Guid GetTemplateIdOrPageId(PageModelBase pageBase)
        {
            Guid id = Guid.Empty;
            if (pageBase is PageTemplateModel template)
            {
                id = template.TemplateID;
            }
            else if (pageBase is PageModel page)
            {
                id = page.PageID;
            }

            return id;
        }
    }
}
