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>
    /// Viz命令服务
    /// </summary>
    public class VizCommandService
    {
        /// <summary>
        /// 设置场景
        /// </summary>
        /// <param name="conn">连接</param>
        /// <param name="scene">场景</param>
        /// <param name="layer">图层</param>
        public void SetObject(ConnModel conn, string scene, VizLayer layer)
        {
            if (conn == null)
                throw new ArgumentNullException(nameof(conn));

            if (string.IsNullOrWhiteSpace(scene))
                throw new ArgumentNullException(nameof(scene));

            conn.EndpointManager.Request($"RENDERER*{layer} SET_OBJECT SCENE*{scene}");
        }

        /// <summary>
        /// 设置空场景
        /// </summary>
        /// <param name="conn">连接</param>
        /// <param name="layer">图层</param>
        public void SetObjectEmpty(ConnModel conn, VizLayer layer)
        {
            if (conn == null)
                throw new ArgumentNullException(nameof(conn));

            conn.EndpointManager.Request($"RENDERER*{layer} SET_OBJECT");
        }

        /// <summary>
        /// 重新加载场景
        /// </summary>
        /// <param name="conn">连接</param>
        /// <param name="scene">场景</param>
        public void Reload(ConnModel conn, string scene)
        {
            if (conn == null)
                throw new ArgumentNullException(nameof(conn));

            conn.EndpointManager.Send($"SCENE**{scene} RELOAD");
        }

        /// <summary>
        /// 获取场景图片
        /// </summary>
        /// <param name="conn">连接</param>
        /// <param name="scenePath">场景路径</param>
        public System.Drawing.Bitmap GetSceneImage(ConnModel conn, string scenePath)
        {
            if (conn == null)
                throw new ArgumentNullException(nameof(conn));

            return conn.EndpointManager.RequestImage($"peak_get_icon SCENE*{scenePath}");
        }

        /// <summary>
        /// 播放
        /// </summary>
        /// <param name="conn">连接</param>
        /// <param name="scene">场景</param>
        /// <param name="layer">图层</param>
        public void Start(ConnModel conn, string scene, VizLayer layer)
        {
            if (conn == null)
                throw new ArgumentNullException(nameof(conn));

            if (string.IsNullOrWhiteSpace(scene))
            {
                conn.EndpointManager.Send($"RENDERER*{layer}*STAGE START");
            }
            else
            {
                conn.EndpointManager.Send($"RENDERER*{layer}*STAGE*DIRECTOR*{scene} START");
            }
        }

        /// <summary>
        /// 继续
        /// </summary>
        /// <param name="conn">连接</param>
        /// <param name="scene">场景</param>
        /// <param name="layer">图层</param>
        public void Continue(ConnModel conn, string scene, VizLayer layer)
        {
            if (conn == null)
                throw new ArgumentNullException(nameof(conn));

            if (string.IsNullOrWhiteSpace(scene))
            {
                conn.EndpointManager.Send($"RENDERER*{layer}*STAGE CONTINUE");
            }
            else
            {
                conn.EndpointManager.Send($"RENDERER*{layer}*STAGE*DIRECTOR*{scene} CONTINUE");
            }
        }

        /// <summary>
        /// 停止
        /// </summary>
        /// <param name="conn">连接</param>
        /// <param name="scene">场景</param>
        /// <param name="layer">图层</param>
        public void Stop(ConnModel conn, string scene, VizLayer layer)
        {
            if (conn == null)
                throw new ArgumentNullException(nameof(conn));

            if (string.IsNullOrWhiteSpace(scene))
            {
                conn.EndpointManager.Send($"RENDERER*{layer}*STAGE STOP");
            }
            else
            {
                conn.EndpointManager.Send($"RENDERER*{layer}*STAGE*DIRECTOR*{scene} STOP");
            }
        }

        /// <summary>
        /// 显示安全框
        /// </summary>
        /// <param name="conn">连接</param>
        /// <param name="show">是否显示</param>
        public void ShowTS(ConnModel conn, bool show)
        {
            if (conn == null)
                throw new ArgumentNullException(nameof(conn));

            VizConfigEntity config = ApplicationDomainEx.VizConfig;

            if (config.EngineFullType == EngineFullType.VIZ_Eng3)
            {
                conn.EndpointManager.Send($"RENDERER SET_TITLE_AREA {(show ? 1 : 0)}");
            }
            else if (config.EngineFullType == EngineFullType.VIZ_Eng4)
            {
                conn.EndpointManager.Send($"{ApplicationDomainEx.VizPreviewRenderer} SET_TITLE_AREA {(show ? 1 : 0)}");
            }
        }

        /// <summary>
        /// 显示安区域
        /// </summary>
        /// <param name="conn">连接</param>
        /// <param name="show">是否显示</param>
        public void ShowSA(ConnModel conn, bool show)
        {
            if (conn == null)
                throw new ArgumentNullException(nameof(conn));

            VizConfigEntity config = ApplicationDomainEx.VizConfig;

            if (config.EngineFullType == EngineFullType.VIZ_Eng3)
            {
                conn.EndpointManager.Send($"RENDERER SET_SAFE_AREA {(show ? 1 : 0)}");
            }
            else if (config.EngineFullType == EngineFullType.VIZ_Eng4)
            {
                conn.EndpointManager.Send($"{ApplicationDomainEx.VizPreviewRenderer} SET_SAFE_AREA {(show ? 1 : 0)}");
            }
        }

        /// <summary>
        /// 显示边界框
        /// </summary>
        /// <param name="conn">连接</param>
        /// <param name="show">是否显示</param>
        public void ShowBB(ConnModel conn, bool show)
        {
            if (conn == null)
                throw new ArgumentNullException(nameof(conn));

            VizConfigEntity config = ApplicationDomainEx.VizConfig;

            if (config.EngineFullType == EngineFullType.VIZ_Eng3)
            {
                conn.EndpointManager.Send($"RENDERER SHOW_BOUNDING_BOX {(show ? 1 : 0)}");
            }
            else if (config.EngineFullType == EngineFullType.VIZ_Eng4)
            {
                conn.EndpointManager.Send($"{ApplicationDomainEx.VizPreviewRenderer} SHOW_BOUNDING_BOX {(show ? 1 : 0)}");
            }
        }

        /// <summary>
        /// 显示RGB
        /// </summary>
        /// <param name="conn">连接</param>
        public void ShowRGB(ConnModel conn)
        {
            if (conn == null)
                throw new ArgumentNullException(nameof(conn));

            VizConfigEntity config = ApplicationDomainEx.VizConfig;

            if (config.EngineFullType == EngineFullType.VIZ_Eng3)
            {
                conn.EndpointManager.Send($"RENDERER SET_KEY 0,RENDERER*KEY_INTERNAL*ACTIVE SET 0");
            }
            else if (config.EngineFullType == EngineFullType.VIZ_Eng4)
            {
                conn.EndpointManager.Send($"{ApplicationDomainEx.VizPreviewRenderer} SET_KEY 0,RENDERER*KEY_INTERNAL*ACTIVE SET 0");
            }
        }

        /// <summary>
        /// 显示键
        /// </summary>
        /// <param name="conn">连接</param>
        public void ShowKey(ConnModel conn)
        {
            if (conn == null)
                throw new ArgumentNullException(nameof(conn));

            VizConfigEntity config = ApplicationDomainEx.VizConfig;

            if (config.EngineFullType == EngineFullType.VIZ_Eng3)
            {
                conn.EndpointManager.Send($"RENDERER SET_KEY 1,RENDERER*KEY_INTERNAL*ACTIVE SET 0");
            }
            else if (config.EngineFullType == EngineFullType.VIZ_Eng4)
            {
                conn.EndpointManager.Send($"{ApplicationDomainEx.VizPreviewRenderer} SET_KEY 1,RENDERER*KEY_INTERNAL*ACTIVE SET 0");
            }
        }

        /// <summary>
        /// 显示预览键
        /// </summary>
        /// <param name="conn">连接</param>
        public void ShowKeyPreview(ConnModel conn)
        {
            if (conn == null)
                throw new ArgumentNullException(nameof(conn));

            VizConfigEntity config = ApplicationDomainEx.VizConfig;

            if (config.EngineFullType == EngineFullType.VIZ_Eng3)
            {
                conn.EndpointManager.Send($"RENDERER SET_KEY 0,RENDERER*KEY_INTERNAL*IMAGE RESET,RENDERER*KEY_INTERNAL*ACTIVE SET 1");
            }
            else if (config.EngineFullType == EngineFullType.VIZ_Eng4)
            {
                conn.EndpointManager.Send($"{ApplicationDomainEx.VizPreviewRenderer} SET_KEY 0,RENDERER*KEY_INTERNAL*IMAGE RESET,RENDERER*KEY_INTERNAL*ACTIVE SET 1");
            }
        }

        /// <summary>
        /// 设置更新
        /// </summary>
        /// <param name="conn">连接</param>
        /// <param name="isEnabled">是否启用</param>
        public void SetEnabledUpdate(ConnModel conn, bool isEnabled)
        {
            conn.EndpointManager.Send($"RENDERER*UPDATE SET {(isEnabled ? 1 : 0)}");
        }

        /// <summary>
        /// 开始动画
        /// </summary>
        /// <param name="conn">连接</param>
        /// <param name="layer">层</param>
        public void Start(ConnModel conn, VizLayer layer)
        {
            conn.EndpointManager.Send($"RENDERER*{layer}*STAGE START");
        }

        /// <summary>
        /// 继续版子
        /// </summary>
        /// <param name="conn">连接</param>
        /// <param name="layer">层</param>
        public void TakeContinue(ConnModel conn, VizLayer layer)
        {
            conn.EndpointManager.Send($"RENDERER*UPDATE SET 1");
            conn.EndpointManager.Send($"RENDERER*{layer}*STAGE CONTINUE");
        }

        /// <summary>
        /// 下版子
        /// </summary>
        /// <param name="conn">连接</param>
        /// <param name="layer">层</param>s
        public void TakeOut(ConnModel conn, VizLayer layer)
        {
            conn.EndpointManager.Send($"RENDERER*UPDATE SET 1");
            conn.EndpointManager.Send($"RENDERER*{layer} SET_OBJECT");
        }

        /// <summary>
        /// 获取场景名
        /// </summary>
        /// <param name="conn">连接</param>
        /// <param name="layer">层</param>
        /// <returns>场景名</returns>
        public string GetSceneName(ConnModel conn, VizLayer layer)
        {
            VizScene scene = VizScene.MAIN_SCENE;

            switch (layer)
            {
                case VizLayer.FRONT_LAYER: scene = VizScene.FRONT_SCENE; break;
                case VizLayer.MAIN_LAYER: scene = VizScene.MAIN_SCENE; break;
                case VizLayer.BACK_LAYER: scene = VizScene.BACK_SCENE; break;
            }

            return this.GetSceneName(conn, scene);
        }

        /// <summary>
        /// 获取场景名
        /// </summary>
        /// <param name="conn">连接</param>
        /// <param name="scene">场景</param>
        /// <returns>场景名</returns>
        public string GetSceneName(ConnModel conn, VizScene scene)
        {
            string sceneName = conn.EndpointManager.Request($"{scene}*NAME GET");
            return sceneName;
        }

        /// <summary>
        /// 清理页
        /// </summary>
        /// <param name="conn">连接</param>
        public void TakeClear(ConnModel conn)
        {
            conn.EndpointManager.Request("RENDERER*FRONT_LAYER SET_OBJECT");
            conn.EndpointManager.Request("RENDERER*MAIN_LAYER SET_OBJECT");
            conn.EndpointManager.Request("RENDERER*BACK_LAYER SET_OBJECT");
            conn.EndpointManager.Request("SCENE CLEANUP");
            conn.EndpointManager.Request("GEOM CLEANUP");
            conn.EndpointManager.Request("IMAGE CLEANUP");
            conn.EndpointManager.Request("FONT CLEANUP");
            conn.EndpointManager.Request("MATERIAL CLEANUP");
            conn.EndpointManager.Request("MAPS CACHE CLEANUP");
        }

        /// <summary>
        /// 初始化页
        /// </summary>
        /// <param name="conn">连接</param>
        /// <param name="scene">场景</param>
        /// <returns>初始化返回</returns>
        public string TakeInit(ConnModel conn, string scene)
        {
            return conn.EndpointManager.Request($"SCENE*{scene} LOAD");
        }

        // --------------------------------------------------------------------------------------------------
        // GROUP

        /// <summary>
        /// 设置分组名称
        /// </summary>
        /// <param name="conn">连接</param>
        /// <param name="vizID">VizID</param>
        /// <param name="name">名称</param>
        public void GroupSetName(ConnModel conn, string vizID, string name)
        {
            conn.EndpointManager.Send($"#{vizID}*NAME SET {name}");
        }

        /// <summary>
        /// 删除分组
        /// </summary>
        /// <param name="conn">连接</param>
        /// <param name="vizID">VizID</param>
        /// <param name="name">名称</param>
        public void GroupDelete(ConnModel conn, string scenePath, string vizID)
        {
            conn.EndpointManager.Send($"SCENE*{scenePath}*TREE*#{vizID} DELETE ALL");
        }

        /// <summary>
        /// 添加分组
        /// </summary>
        /// <param name="conn">连接</param>
        /// <param name="scenePath">场景路径</param>
        /// <param name="controlObjectVizID">控制对象ID</param>
        /// <param name="direction">移动位置</param>
        /// <returns>添加的分组树节点路径</returns>
        public string GroupAdd(ConnModel conn, string scenePath, string controlObjectVizID, VizGroupMoveDirection direction)
        {
            return conn.EndpointManager.Request($"SCENE*{scenePath}*TREE*#{controlObjectVizID} ADD {direction}");
        }

        /// <summary>
        /// 移动分组
        /// </summary>
        /// <param name="conn">连接</param>
        /// <param name="scenePath">场景路径</param>
        /// <param name="srcVizID">源VizID</param>
        /// <param name="destVizID">目标VizID</param>
        /// <param name="direction">移动位置</param>
        public void GroupMove(ConnModel conn, string scenePath, string srcVizID, string destVizID, VizGroupMoveDirection direction)
        {
            conn.EndpointManager.Send($"SCENE*{scenePath}*TREE*#{srcVizID} MOVE SCENE*{scenePath}*TREE*#{destVizID} {direction}");
        }

        // --------------------------------------------------------------------------------------------------
        // GEOM

        /// <summary>
        /// GEOM 打包
        /// </summary>
        /// <param name="conn">连接</param>
        /// <param name="scenePath">场景</param>
        /// <param name="vizID">VizID</param>
        public void GeomGroup(ConnModel conn, string scenePath, string vizID)
        {
            conn.EndpointManager.Send($"SCENE*{scenePath}*TREE*#{vizID}*GEOM GROUP");
        }

        /// <summary>
        /// GEOM 解包
        /// </summary>
        /// <param name="conn">连接</param>
        /// <param name="scenePath">场景</param>
        /// <param name="vizID">VizID</param>
        public void GeomUnGroup(ConnModel conn, string scenePath, string vizID)
        {
            conn.EndpointManager.Send($"SCENE*{scenePath}*TREE*#{vizID}*GEOM UNGROUP");
        }

        /// <summary>
        /// 获取GEOM
        /// </summary>
        /// <param name="conn">连接</param>
        /// <param name="scenePath">场景</param>
        /// <param name="vizID">VizID</param>
        /// <returns>GEOM VizID</returns>
        public string GeomGet(ConnModel conn, string scenePath, string vizID)
        {
            string result = conn.EndpointManager.Request($"SCENE*{scenePath}*TREE*#{vizID}*GEOM GET");
            if (string.IsNullOrWhiteSpace(result) || result.StartsWith(ApplicationConstants.VIZ_COMMAND_RESULT_ERROR_PREFIX))
                return null;

            string[] pars = result.Split('#');
            if (pars.Length < 2)
                return null;

            return pars[1];
        }

        /// <summary>
        /// 拷贝GEOM
        /// </summary>
        /// <param name="conn">连接</param>
        /// <param name="srcVizID">源VizID</param>
        /// <param name="destPath">目标路径</param>
        /// <returns>是否成功拷贝</returns>
        public bool GeomCopy(ConnModel conn, string srcVizID, string destPath)
        {
            string result = conn.EndpointManager.Request($"GEOM*#{srcVizID} COPY GEOM*{destPath}");
            return string.Equals(result, "1");
        }

        // --------------------------------------------------------------------------------------------------
        // 切换场景

        /// <summary>
        /// 动画显示
        /// </summary>
        /// <param name="conn">连接</param>
        /// <param name="layer">逻辑层</param>
        /// <param name="state">状态</param>
        public void DirectorShowWithTransitionLogic(ConnModel conn, string bgScenePath, string layer, string state)
        {
            if (conn == null)
                throw new ArgumentNullException(nameof(conn));

            if (string.IsNullOrWhiteSpace(bgScenePath))
                throw new ArgumentNullException(nameof(bgScenePath));

            if (string.IsNullOrWhiteSpace(layer))
                throw new ArgumentNullException(nameof(layer));

            if (string.IsNullOrWhiteSpace(state))
                throw new ArgumentNullException(nameof(state));

            conn.EndpointManager.Send($"SCENE*{bgScenePath}*STAGE*DIRECTOR*{layer} SHOW ${state}");
        }

        /// <summary>
        /// 动画切换
        /// </summary>
        /// <param name="conn">连接</param>
        /// <param name="layer">逻辑层</param>
        /// <param name="oldState">旧状态</param>
        /// <param name="newState">新状态</param>
        public void DirectorGoToWithTransitionLogic(ConnModel conn, string layer, string oldState, string newState)
        {
            if (conn == null)
                throw new ArgumentNullException(nameof(conn));

            if (string.IsNullOrWhiteSpace(layer))
                throw new ArgumentNullException(nameof(layer));

            if (string.IsNullOrWhiteSpace(oldState))
                throw new ArgumentNullException(nameof(oldState));

            if (string.IsNullOrWhiteSpace(newState))
                throw new ArgumentNullException(nameof(newState));

            conn.EndpointManager.Send($"RENDERER*MAIN_LAYER*STAGE*DIRECTOR*{layer} GOTO_TRIO ${oldState} ${newState}");
        }

        /// <summary>
        /// 设置切换逻辑层的GEOM
        /// </summary>
        /// <param name="conn">连接</param>
        /// <param name="bgScene">背景场景</param>
        /// <param name="layer">逻辑层</param>
        /// <param name="scene">场景</param>
        public void ToggleSetGeomWithTransitionLogic(ConnModel conn, string bgScene, string layer, string scene)
        {
            if (conn == null)
                throw new ArgumentNullException(nameof(conn));

            if (string.IsNullOrWhiteSpace(scene))
                throw new ArgumentNullException(nameof(scene));

            conn.EndpointManager.Send($"SCENE*{bgScene}*TREE*${layer}*FUNCTION*Toggle*object SET GEOM*{scene}");
        }

        /// <summary>
        /// 设置切换逻辑层的对象
        /// </summary>
        /// <param name="conn">连接</param>
        /// <param name="pageBase">页</param>
        public void ToggleSetWithTransitionLogic(ConnModel conn, PageModelBase pageBase)
        {
            if (conn == null)
                throw new ArgumentNullException(nameof(conn));

            if (pageBase == null)
                throw new ArgumentNullException(nameof(pageBase));

            string scenePathDir = pageBase.ScenePath.Substring(0, pageBase.ScenePath.LastIndexOf('/'));
            string bgScenePath = $"{scenePathDir}/{pageBase.BackgroundScene}";

            conn.EndpointManager.Send($"SCENE*{bgScenePath}*TREE*${pageBase.LayerIdentifier}*FUNCTION*Toggle*object SET");
        }

        /// <summary>
        /// 触发切换
        /// </summary>
        /// <param name="conn">连接</param>
        /// <param name="pageBase">页</param>
        public void ToggleSwitchWithTransitionLogic(ConnModel conn, PageModelBase pageBase)
        {
            if (conn == null)
                throw new ArgumentNullException(nameof(conn));

            if (pageBase == null)
                throw new ArgumentNullException(nameof(pageBase));

            conn.EndpointManager.Send($"RENDERER*MAIN_LAYER*TREE*${pageBase.LayerIdentifier}*FUNCTION*Toggle*switch INVOKE");
        }

        /// <summary>
        /// 触发重置
        /// </summary>
        /// <param name="conn">连接</param>
        /// <param name="bgScenePath">逻辑场景</param>
        /// <param name="logicLayer">切换逻辑层</param>
        public void ToggleResetWithTransitionLogic(ConnModel conn, string bgScenePath, string logicLayer)
        {
            if (conn == null)
                throw new ArgumentNullException(nameof(conn));

            if (string.IsNullOrWhiteSpace(bgScenePath))
                throw new ArgumentNullException(nameof(bgScenePath));

            if (string.IsNullOrWhiteSpace(logicLayer))
                throw new ArgumentNullException(nameof(logicLayer));

            conn.EndpointManager.Send($"SCENE*{bgScenePath}*TREE*${logicLayer}*FUNCTION*Toggle*reset_current INVOKE");
        }

        /// <summary>
        /// 触发继续
        /// </summary>
        /// <param name="conn">连接</param>
        /// <param name="pageBase">页</param>
        public void ToggleContinueWithTransitionLogic(ConnModel conn, PageModelBase pageBase)
        {
            if (conn == null)
                throw new ArgumentNullException(nameof(conn));

            if (pageBase == null)
                throw new ArgumentNullException(nameof(pageBase));

            conn.EndpointManager.Send($"RENDERER*MAIN_LAYER*TREE*${pageBase.LayerIdentifier}*FUNCTION*Toggle*continue INVOKE");
        }

        public void ClearSceen(ConnModel conn, VizLayer layer)
        {
            conn.EndpointManager.Send($"RENDERER*{layer} SET_OBJECT");

        }
    }
}
