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

namespace VIZ.Package.Module
{
    /// <summary>
    /// 播出控制控制器
    /// </summary>
    public class ControlController
    {
        /// <summary>
        /// 日志
        /// </summary>
        private readonly static ILog log = LogManager.GetLogger(typeof(ControlController));

        /// <summary>
        /// Viz命令服务
        /// </summary>
        private VizCommandService vizCommandService = new VizCommandService();

        /// <summary>
        /// Viz控制对象命令服务
        /// </summary>
        private VizCommandControlObjectService vizCommandControlObjectService = new VizCommandControlObjectService();

        // ---------------------------------------------------------------------------
        // 上版

        /// <summary>
        /// 上版 -- 正常板子
        /// </summary>
        /// <param name="oldPageBase">老的页基类</param>
        /// <param name="newPageBase">新的页基类</param>
        /// <param name="obj">控制对象</param>
        /// <param name="view">插件视图</param>
        /// <param name="conn">连接</param>
        public void TakeNormal(PageModelBase oldPageBase, PageModelBase newPageBase, ControlObjectModel obj, IPluginView view, ConnModel conn)
        {
            // 切换场景
            this.vizCommandService.SetEnabledUpdate(conn, false);
            try
            {
                this.vizCommandService.SetObject(conn, ApplicationDomainEx.CurrentPage.ScenePath, ApplicationDomainEx.CurrentPage.Layer);
                if (obj != null)
                {
                    this.vizCommandControlObjectService.SetControlObject(conn, obj, newPageBase.GetVizScene());
                    this.vizCommandControlObjectService.SetCustomControlFieldValue(conn, obj.AllFiledNodes);
                }
                if (view != null)
                {
                    view.TakIn(conn);
                }
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
            this.vizCommandService.SetEnabledUpdate(conn, true);
            this.vizCommandService.Start(conn, ApplicationDomainEx.CurrentPage.Layer);
        }

        /// <summary>
        /// 上版 -- 切换逻辑
        /// </summary>
        /// <param name="oldPageBase">老的页基类</param>
        /// <param name="newPageBase">新的页基类</param>
        /// <param name="obj">控制对象</param>
        /// <param name="view">插件视图</param>
        /// <param name="conn">连接</param>
        public void TakeTransitionLogic(PageModelBase oldPageBase, PageModelBase newPageBase, ControlObjectModel obj, IPluginView view, ConnModel conn)
        {
            // 场景信息
            SceneInfoModel oldSceneInfo = oldPageBase.GetSceneInfo();
            SceneInfoModel newSceneInfo = newPageBase.GetSceneInfo();
            TransitionLogicSceneInfoModel bgSceneInfo = ApplicationDomainEx.GetSceneInfoWithTransitionLogic(conn, newPageBase);

            // 切换逻辑层
            TransitionLogicLayerInfo transitionLogicLayer = bgSceneInfo.TransitionLogic.LayerInfos.FirstOrDefault(p => p.LayerIdentifier == newPageBase.LayerIdentifier);
            if (transitionLogicLayer == null)
            {
                transitionLogicLayer = new TransitionLogicLayerInfo();
                transitionLogicLayer.LayerIdentifier = ApplicationDomainEx.CurrentPage.LayerIdentifier;
                transitionLogicLayer.StateIdentifier = ApplicationConstants.VIZ_TRANSITIONLOGIC_DEFAULT_OUT;
                transitionLogicLayer.BackgroundScene = ApplicationDomainEx.CurrentPage.BackgroundScene;

                bgSceneInfo.TransitionLogic.LayerInfos.Add(transitionLogicLayer);
            }

            // 当前逻辑层场景是否为将要上的场景
            bool isCurrent = !string.IsNullOrWhiteSpace(transitionLogicLayer.SceneIdentifier) && string.Equals(transitionLogicLayer.SceneIdentifier, newPageBase.Scene);
            // 当前逻辑层是否被占用
            bool isUsed = !string.IsNullOrWhiteSpace(transitionLogicLayer.SceneIdentifier);
            // 背景场景路径
            string bgScenePath = $"{newPageBase.GetSceneParent()}/{newPageBase.BackgroundScene}";
            // 获取当前场景名
            string sceneName = this.vizCommandService.GetSceneName(conn, VizLayer.MAIN_LAYER);
            // 获取当前控制对象值
            string controlObjectValue = this.vizCommandControlObjectService.GetControlObjectStringWithTransitionLogic(obj);

            // RENDERER*UPDATE SET 1
            this.vizCommandService.SetEnabledUpdate(conn, true);

            // 如果当前场景不是指定的背景场景
            if (!string.Equals(newPageBase.BackgroundScene, sceneName))
            {
                foreach (TransitionLogicLayerInfo logicLayer in bgSceneInfo.TransitionLogic.LayerInfos)
                {
                    // SCENE*TITLES/2022/YC/BG1*STAGE*DIRECTOR*DJ_CUP SHOW $O
                    this.vizCommandService.DirectorShowWithTransitionLogic(conn, bgScenePath, logicLayer.LayerIdentifier, ApplicationConstants.VIZ_TRANSITIONLOGIC_DEFAULT_OUT);
                    // SCENE*TITLES/2022/YC/BG1*TREE*$DJ_CUP*FUNCTION*Toggle*reset_current INVOKE
                    this.vizCommandService.ToggleResetWithTransitionLogic(conn, bgScenePath, logicLayer.LayerIdentifier);

                    // 清理状态
                    logicLayer.SceneIdentifier = null;
                    logicLayer.ControlObject = null;
                    logicLayer.IsContinued = false;
                    logicLayer.StateIdentifier = ApplicationConstants.VIZ_TRANSITIONLOGIC_DEFAULT_OUT;
                }
            }

            // RENDERER*MAIN_LAYER SET_OBJECT SCENE*TITLES/2022/YC/BG1
            this.vizCommandService.SetObject(conn, bgScenePath, VizLayer.MAIN_LAYER);

            // 如果当前场景不是指定的背景场景
            if (!string.Equals(newPageBase.BackgroundScene, sceneName))
            {
                // SCENE*TITLES/2022/YC/BG1*TREE*$DJ_CUP*FUNCTION*Toggle*reset_current INVOKE
                this.vizCommandService.ToggleResetWithTransitionLogic(conn, bgScenePath, newPageBase.LayerIdentifier);
            }

            // SCENE*TITLES/2022/YC/BG1*TREE*$DJ_CUP*FUNCTION*Toggle*object SET GEOM*TITLES/2022/YC/YC_CUP
            this.vizCommandService.ToggleSetGeomWithTransitionLogic(conn, bgScenePath, newPageBase.LayerIdentifier, newPageBase.ScenePath);
            transitionLogicLayer.SceneIdentifier = newPageBase.Scene;

            // 如果当前逻辑层场景没有改变，且控制对象值没有发生改变，那么不处理
            if (isCurrent && string.Equals(transitionLogicLayer.ControlObject, controlObjectValue) && !transitionLogicLayer.IsContinued)
            {
                return;
            }

            // 上控制对象信息
            if (obj != null)
            {
                // SCENE*TITLES/2022/YC/BG1*TREE*$DJ_CUP$other$object*FUNCTION*ControlObject*in ......
                this.vizCommandControlObjectService.SetControlObjectOtherWithTransitionLogic(conn, obj, newPageBase);
            }

            // 当前场景是否被占用
            if (isUsed && string.Equals(newPageBase.BackgroundScene, sceneName))
            {
                // RENDERER*MAIN_LAYER*STAGE*DIRECTOR*DJ_CUP SHOW $IN
                this.vizCommandService.DirectorShowWithTransitionLogic(conn, bgScenePath, newPageBase.LayerIdentifier, newPageBase.StateIdentifier);

                // RENDERER*MAIN_LAYER*TREE*$DJ_CUP*FUNCTION*Toggle*switch INVOKE
                this.vizCommandService.ToggleSwitchWithTransitionLogic(conn, newPageBase);
            }
            else
            {
                // RENDERER*MAIN_LAYER*STAGE*DIRECTOR*DJ_CUP GOTO_TRIO $O $IN
                this.vizCommandService.DirectorGoToWithTransitionLogic(conn, transitionLogicLayer.LayerIdentifier, transitionLogicLayer.StateIdentifier, newPageBase.StateIdentifier);
            }

            // 执行插件脚本
            if (view != null)
            {
                view.TakIn(conn);
            }

            // 设置切换逻辑层场景 为 当前场景
            transitionLogicLayer.SceneIdentifier = newPageBase.Scene;
            transitionLogicLayer.StateIdentifier = newPageBase.StateIdentifier;
            transitionLogicLayer.ControlObject = controlObjectValue;
        }

        /// <summary>
        /// 上版 -- 命令
        /// </summary>
        /// <param name="pageBase">页</param>
        /// <param name="conn">连接</param>
        public void TakeCommnad(PageModelBase pageBase, ConnModel conn)
        {
            // 执行命令
            IPageCommandService pageCommandService = ApplicationDomainEx.ServiceManager.GetService<IPageCommandService>(ViewServiceKeys.PAGE_COMMAND_SERVICE);
            if (pageCommandService == null)
                return;

            pageCommandService.BeginExecuteTakeCommand(pageBase, conn);
        }

        // ---------------------------------------------------------------------------
        // 继续

        /// <summary>
        /// 继续 -- 正常板子
        /// </summary>
        /// <param name="oldPageBase">老的页基类</param>
        /// <param name="newPageBase">新的页基类</param>
        /// <param name="obj">控制对象</param>
        /// <param name="view">插件视图</param>
        /// <param name="conn">连接</param>
        public void ContinueNormal(PageModelBase oldPageBase, PageModelBase newPageBase, ControlObjectModel obj, IPluginView view, ConnModel conn)
        {
            this.vizCommandService.TakeContinue(conn, newPageBase.Layer);
            view?.TakeContinue(conn);

            // 执行命令
            IPageCommandService pageCommandService = ApplicationDomainEx.ServiceManager.GetService<IPageCommandService>(ViewServiceKeys.PAGE_COMMAND_SERVICE);
            if (pageCommandService == null)
                return;

            pageCommandService.BeginExecuteTakeContinueCommand(ApplicationDomainEx.CurrentPage, conn);
        }

        /// <summary>
        /// 继续 -- 切换逻辑
        /// </summary>
        /// <param name="oldPageBase">老的页基类</param>
        /// <param name="newPageBase">新的页基类</param>
        /// <param name="obj">控制对象</param>
        /// <param name="view">插件视图</param>
        /// <param name="conn">连接</param>
        public void ContinueTransitionLogic(PageModelBase oldPageBase, PageModelBase newPageBase, ControlObjectModel obj, IPluginView view, ConnModel conn)
        {
            this.vizCommandService.SetEnabledUpdate(conn, true);
            this.vizCommandService.ToggleContinueWithTransitionLogic(conn, newPageBase);
            if (view != null)
            {
                view.TakeContinue(conn);
            }

            // 切换逻辑层
            TransitionLogicSceneInfoModel bgSceneInfo = ApplicationDomainEx.GetSceneInfoWithTransitionLogic(conn, newPageBase);

            TransitionLogicLayerInfo logicLayer = bgSceneInfo.TransitionLogic.LayerInfos.FirstOrDefault(p => p.LayerIdentifier == newPageBase.LayerIdentifier);
            if (logicLayer != null)
            {
                logicLayer.IsContinued = true;
            }

            // 执行命令
            IPageCommandService pageCommandService = ApplicationDomainEx.ServiceManager.GetService<IPageCommandService>(ViewServiceKeys.PAGE_COMMAND_SERVICE);
            if (pageCommandService == null)
                return;

            pageCommandService.BeginExecuteTakeContinueCommand(ApplicationDomainEx.CurrentPage, conn);
        }

        /// <summary>
        /// 继续 -- 命令
        /// </summary>
        /// <param name="pageBase">页</param>
        /// <param name="conn">连接</param>
        public void ContinueCommnad(PageModelBase pageBase, ConnModel conn)
        {
            // 执行命令
            IPageCommandService pageCommandService = ApplicationDomainEx.ServiceManager.GetService<IPageCommandService>(ViewServiceKeys.PAGE_COMMAND_SERVICE);
            if (pageCommandService == null)
                return;

            pageCommandService.BeginExecuteTakeContinueCommand(pageBase, conn);
        }

        // ---------------------------------------------------------------------------
        // 下板

        /// <summary>
        /// 下板 -- 正常板子
        /// </summary>
        /// <param name="oldPageBase">老的页基类</param>
        /// <param name="newPageBase">新的页基类</param>
        /// <param name="obj">控制对象</param>
        /// <param name="view">插件视图</param>
        /// <param name="conn">连接</param>
        public void TakeOutNormal(PageModelBase oldPageBase, PageModelBase newPageBase, ControlObjectModel obj, IPluginView view, ConnModel conn)
        {
            this.vizCommandService.TakeOut(conn, newPageBase.Layer);
            view?.TakeOut(conn);
        }

        /// <summary>
        /// 下板 -- 切换逻辑
        /// </summary>
        /// <param name="oldPageBase">老的页基类</param>
        /// <param name="newPageBase">新的页基类</param>
        /// <param name="obj">控制对象</param>
        /// <param name="view">插件视图</param>
        /// <param name="conn">连接</param>
        public void TakeOutTransitionLogic(PageModelBase oldPageBase, PageModelBase newPageBase, ControlObjectModel obj, IPluginView view, ConnModel conn)
        {
            // 场景信息
            TransitionLogicSceneInfoModel bgSceneInfo = ApplicationDomainEx.GetSceneInfoWithTransitionLogic(conn, newPageBase);

            // 切换逻辑层
            TransitionLogicLayerInfo transitionLogicLayer = bgSceneInfo.TransitionLogic.LayerInfos.FirstOrDefault(p => p.LayerIdentifier == newPageBase.LayerIdentifier);

            if (transitionLogicLayer == null || string.Equals(transitionLogicLayer.StateIdentifier, ApplicationConstants.VIZ_TRANSITIONLOGIC_DEFAULT_OUT))
                return;

            string bgScenePath = $"{newPageBase.GetSceneParent()}/{ApplicationDomainEx.CurrentPage.BackgroundScene}";

            this.vizCommandService.SetEnabledUpdate(conn, true);
            this.vizCommandService.SetObject(conn, bgScenePath, VizLayer.MAIN_LAYER);
            this.vizCommandService.ToggleSetWithTransitionLogic(conn, newPageBase);
            this.vizCommandService.DirectorGoToWithTransitionLogic(conn, transitionLogicLayer.LayerIdentifier, transitionLogicLayer.StateIdentifier, ApplicationConstants.VIZ_TRANSITIONLOGIC_DEFAULT_OUT);
            view?.TakeOut(conn);

            // 切换逻辑层
            SceneInfoModel sceneInfo = newPageBase.GetSceneInfo();
            TransitionLogicLayerInfo logicLayer = bgSceneInfo.TransitionLogic.LayerInfos.FirstOrDefault(p => p.LayerIdentifier == newPageBase.LayerIdentifier);
            bgSceneInfo.TransitionLogic.LayerInfos.Remove(logicLayer);
        }

        /// <summary>
        /// 下版 -- 命令
        /// </summary>
        /// <param name="pageBase">页</param>
        /// <param name="conn">连接</param>
        public void TakeOutCommnad(PageModelBase pageBase, ConnModel conn)
        {
            // 执行命令
            IPageCommandService pageCommandService = ApplicationDomainEx.ServiceManager.GetService<IPageCommandService>(ViewServiceKeys.PAGE_COMMAND_SERVICE);
            if (pageCommandService == null)
                return;

            pageCommandService.BeginExecuteTakeOutCommand(pageBase, conn);
        }

        // ---------------------------------------------------------------------------
        // 更新

        /// <summary>
        /// 更新 -- 正常板子
        /// </summary>
        /// <param name="oldPageBase">老的页基类</param>
        /// <param name="newPageBase">新的页基类</param>
        /// <param name="obj">控制对象</param>
        /// <param name="view">插件视图</param>
        /// <param name="conn">连接</param>
        public void UpdateNormal(PageModelBase oldPageBase, PageModelBase newPageBase, ControlObjectModel obj, IPluginView view, ConnModel conn)
        {
            this.vizCommandService.SetEnabledUpdate(conn, false);
            try
            {
                if (obj != null)
                {
                    this.vizCommandControlObjectService.SetControlObject(conn, obj, newPageBase.GetVizScene());
                    this.vizCommandControlObjectService.SetCustomControlFieldValue(conn, obj.AllFiledNodes);
                }
                view?.TakeUpdate(conn);
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
            this.vizCommandService.SetEnabledUpdate(conn, true);
        }

        /// <summary>
        /// 更新 -- 切换逻辑
        /// </summary>
        /// <param name="oldPageBase">老的页基类</param>
        /// <param name="newPageBase">新的页基类</param>
        /// <param name="obj">控制对象</param>
        /// <param name="view">插件视图</param>
        /// <param name="conn">连接</param>
        public void UpdateTransitionLogic(PageModelBase oldPageBase, PageModelBase newPageBase, ControlObjectModel obj, IPluginView view, ConnModel conn)
        {
            string bgScenePath = $"{newPageBase.GetSceneParent()}/{ApplicationDomainEx.CurrentPage.BackgroundScene}";

            this.vizCommandService.SetEnabledUpdate(conn, true);
            this.vizCommandService.SetObject(conn, bgScenePath, VizLayer.MAIN_LAYER);
            if (obj != null)
            {
                this.vizCommandControlObjectService.SetControlObjectCurrentWithTransitionLogic(conn, obj, ApplicationDomainEx.CurrentPage);
                // 切换逻辑场景不支持自定义字段
                // this.vizCommandControlObjectService.SetCustomControlObjectWithTransitionLogic(conn, obj, ApplicationDomainEx.CurrentPage);
            }
            if (view != null)
            {
                view.TakeUpdate(conn);
            }
        }

        /// <summary>
        /// 更新 -- 命令
        /// </summary>
        /// <param name="pageBase">页</param>
        /// <param name="conn">连接</param>
        public void UpdateCommnad(PageModelBase pageBase, ConnModel conn)
        {
            // 执行命令
            IPageCommandService pageCommandService = ApplicationDomainEx.ServiceManager.GetService<IPageCommandService>(ViewServiceKeys.PAGE_COMMAND_SERVICE);
            if (pageCommandService == null)
                return;

            pageCommandService.BeginExecuteTakeUpdateCommand(pageBase, conn);
        }
    }
}
