﻿using System.Text;
using JLGames.RocketDriver.Games.NetManager.Virtual;
using JLGames.RocketDriver.Samples.RpgMaterialDemo.Service;
using JLGames.RocketDriver.Samples.RpgMaterialDemo.Service.GM;
using JLGames.RocketDriver.Samples.RpgMaterialDemo.Service.Material;
using UnityEngine;
using UnityEngine.UI;

namespace JLGames.RocketDriver.Samples.RpgMaterialDemo.UI.GM
{
    public class GmPanel : MonoBehaviour
    {
        [SerializeField] private GmMaterialContent m_InsertNode;
        [SerializeField] private GmMaterialContent m_DeleteNode;
        [SerializeField] private GmMaterialContent m_UpdateNode;
        [SerializeField] private GmMaterialContent m_QueryNode;
        [SerializeField] private Text m_MaterialQueryResult;
        private readonly StringBuilder m_SbQuery = new StringBuilder();

        private IGmService GmService => ServiceCenter.GetService<IGmService>(ServiceNames.Gm);

        public void OnClickInsert()
        {
            ClearQueryResultCache();
            var type = m_InsertNode.Type;
            var id = m_InsertNode.Id;
            var num = m_InsertNode.Num;
            TryInsert(type, id, num);
            m_MaterialQueryResult.text = m_SbQuery.ToString();
        }

        public void OnClickUpdate()
        {
            ClearQueryResultCache();
            var type = m_UpdateNode.Type;
            var id = m_UpdateNode.Id;
            var num = m_UpdateNode.Num;
            TryUpdate(type, id, num);
            m_MaterialQueryResult.text = m_SbQuery.ToString();
        }

        public void OnClickDelete()
        {
            ClearQueryResultCache();
            var type = m_DeleteNode.Type;
            var id = m_DeleteNode.Id;
            var num = m_DeleteNode.Num;
            TryDelete(type, id, num);
            m_MaterialQueryResult.text = m_SbQuery.ToString();
        }

        public void OnClickQuery()
        {
            ClearQueryResultCache();
            var type = m_QueryNode.Type;
            var id = m_QueryNode.Id;
            TryQuery(type, id);
            m_MaterialQueryResult.text = m_SbQuery.ToString();
        }

        private void TryInsert(int type, int id, int num)
        {
            var err = CheckMaterial(type, id);
            if (!string.IsNullOrEmpty(err))
            {
                m_SbQuery.Append(err);
                return;
            }

            var gmService = GmService;
            gmService.OnceEventListener(GmServiceEvents.EventOnMaterialInsert,
                evd =>
                {
                    var resp = (VirtualClientResponse) evd.Data;
                    if (resp.RsCode == 0)
                    {
                        m_SbQuery.Append($"插入材料数据【Type={type}, Id={id}】, Num={num} 成功！\n");
                        TryQuery(type, id);
                    }
                    else
                    {
                        m_SbQuery.Append($"插入材料数据【Type={type}, Id={id}】, Num={num} 失败！");
                    }
                });
            gmService.InsertMaterial(type, id, (uint) num);
        }

        private void TryUpdate(int type, int id, int num)
        {
            var err = CheckMaterial(type, id);
            if (!string.IsNullOrEmpty(err))
            {
                m_SbQuery.Append(err);
                return;
            }

            var gmService = GmService;
            gmService.OnceEventListener(GmServiceEvents.EventOnMaterialUpdate,
                evd =>
                {
                    var resp = (VirtualClientResponse) evd.Data;
                    if (resp.RsCode == 0)
                    {
                        m_SbQuery.Append($"更新材料数据【Type={type}, Id={id}】, Num={num} 成功！\n");
                        TryQuery(type, id);
                    }
                    else
                    {
                        m_SbQuery.Append($"更新材料数据【Type={type}, Id={id}】, Num={num} 失败！");
                    }
                });
            gmService.UpdateMaterial(type, id, (uint) num);
        }

        private void TryDelete(int type, int id, int num)
        {
            var err = CheckType(type);
            if (null != err)
            {
                m_SbQuery.Append(err);
                return;
            }

            var um = ServiceCenter.GetMaterialService(type)?.GetUserMaterialAs<IGameUserMaterial>(id);
            if (null == um)
            {
                m_SbQuery.Append($"UserMaterial Id Error: {id}");
                return;
            }

            var mId = um.MId;
            var gmService = GmService;
            gmService.OnceEventListener(GmServiceEvents.EventOnMaterialDelete,
                evd =>
                {
                    var resp = (VirtualClientResponse) evd.Data;
                    if (resp.RsCode == 0)
                    {
                        m_SbQuery.Append($"删除材料数据【Type={type}, Id={id}】, Num={num} 成功！\n");
                        TryQuery(type, mId);
                    }
                    else
                    {
                        m_SbQuery.Append($"删除材料数据【Type={type}, Id={id}】, Num={num} 失败！");
                    }
                });
            gmService.DeleteMaterial(type, id, num);
        }


        private void ClearQueryResultCache()
        {
            m_SbQuery.Clear();
        }

        private void TryQuery(int type, int id)
        {
            var errStr = CheckType(type);
            if (!string.IsNullOrEmpty(errStr))
            {
                m_SbQuery.Append(errStr);
                return;
            }

            var service = ServiceCenter.GetMaterialService(type);
            IGameUserMaterial[] ums = null;
            if (id == 0)
            {
                ums = service.GetUserMaterialsAs<IGameUserMaterial>();
            }
            else
            {
                ums = service.GetUserMaterialsAs<IGameUserMaterial>(id);
            }

            if (null == ums || ums.Length == 0)
            {
                m_SbQuery.Append($"无用户数据：Type={type}, Id={id}");
                return;
            }

            m_SbQuery.Append($"查询材料：Type={type}, Id={id}\n");
            var all = 0;
            foreach (var userMaterial in ums)
            {
                if (userMaterial.Num >= 0 && id != 0) all += userMaterial.Num;
                m_SbQuery.Append(userMaterial);
                m_SbQuery.Append("\n");
            }

            if (id != 0)
            {
                m_SbQuery.Append($"\n总统计数量：{all}");
            }

            return;
        }

        private string CheckMaterial(int type, int mId)
        {
            var rs = CheckType(type);
            if (null != rs) return rs;

            if (!ServiceCenter.GetMaterialService(type).ExistMaterial(mId)) return $"Material Id Error: {mId}";
            return null;
        }

        private string CheckType(int type)
        {
            if (!ServiceRegister.CheckMaterialExist(type)) return $"Material Type Error: {type}";

            var service = ServiceCenter.GetMaterialService(type);
            if (null == service) return $"Service Type Error: {type}";
            return null;
        }
    }
}