using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Threading;
using ActorCore;
using GameData;
using ObjectModel.User;
using Server.AliyunSDK.SLSLog;
using Server.Core;
using Server.Data.Module;
using Server.DB.Sql;

namespace Server
{
    public partial class PropManager : SingleInstance<PropManager>, IDisposable
    {
        private const string TableName = "UserProps";

        private const string PropIdFiledName = "PropId";

        private const string CountFiledName = "Count";

        private Timer _timer;

        public PropManager()
        {
            GameDispatcher.Instance.AddListener(GameMsgId.UserPropChange, OnUserPropChange);
            GameCenterMainActorId = new ActorId((byte)ModuleType.GameCenter, 0, ActorTypeId.Main);
            _timer = new Timer(OnSecondTime, null, 1000, 3 * 1000);
        }


        private Dictionary<int, int> SelectUserProp(int userid)
        {
            Dictionary<int, int> dic = new Dictionary<int, int>();
            string sql = $"SELECT * FROM {TableName} where UserId = @userid";
            DataSet ds = new DataSet();
            GameDB.Instance.ExceSql(dbbase.gamedb, sql, new SqlParameter[]
            {
                new SqlParameter("@userid", userid)
            }, ds);

            if (ds.Tables.Count > 0)
            {
                for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
                {
                    int propId = (int)ds.Tables[0].Rows[i][PropIdFiledName];
                    int count = (int)ds.Tables[0].Rows[i][CountFiledName];
                    dic.Add(propId, count);
                }
            }

            return dic;
        }

        #region 道具日志

        private readonly UserPropLogInfo logBasicInfo = new UserPropLogInfo();
        private readonly UserGoldLogInfo logGoldInfo = new UserGoldLogInfo();

        private readonly ConcurrentQueue<SLSLogData> _propLogQueue = new ConcurrentQueue<SLSLogData>();

        private readonly ConcurrentListPool<SLSLogData> _listPool = new ConcurrentListPool<SLSLogData>();

        /// <summary>
        /// 秒级定时器
        /// </summary>
        private void OnSecondTime(object state)
        {
            SaveUserPropLog();
        }

        private async void SaveUserPropLog()
        {
            if (_propLogQueue.Count <= 0)
            {
                return;
            }

            List<SLSLogData> propList = _listPool.Get();
            List<SLSLogData> goldList = _listPool.Get();
            while (_propLogQueue.TryDequeue(out var item))
            {
                if (item is UserGoldLogData)
                    goldList.Add(item);
                else if (item is UserPropLogData)
                    propList.Add(item);
            }

            //保存日志
            await SLSLogManager.Instance.ReportLog(logBasicInfo, propList);
            await SLSLogManager.Instance.ReportLog(logGoldInfo, goldList);

            foreach (var item in propList)
            {
                item.Dispose();
            }
            
            foreach (var item in goldList)
            {
                item.Dispose();
            }

            _listPool.Recycle(propList);
            _listPool.Recycle(goldList);
        }

        public void AddLog(int userid, int propId, long changeCount, long finalValue, string tag)
        {
            UserPropLogData data = UserPropLogData.Create(userid, propId, changeCount, finalValue,
                ServerConfigManager.Instance.NodeId, ServerConfigManager.Instance.NodeNum, tag);
            _propLogQueue.Enqueue(data);
        }
        
        public void AddGoldLog(int userid, long changeCount, long finalValue, UserGoldLogType logType, string tag)
        {
            UserGoldLogData data = UserGoldLogData.Create(userid, ResName.Gold, logType, changeCount, finalValue,
                ServerConfigManager.Instance.NodeId, ServerConfigManager.Instance.NodeNum, tag);
            _propLogQueue.Enqueue(data);
        }

        public void AddLog(int userid,List<ZiChanLogData> logs)
        {
            foreach (var log in logs)
            {
                if (log.Id == ResName.Gold)
                {
                    AddGoldLog(userid,log.ChangeValue,log.FinValue,log.GoldLogType,log.Tag);
                }
                else
                {
                    AddLog(userid,log.Id,log.ChangeValue,log.FinValue,log.Tag);
                }
            }
        }

        public void Dispose()
        {
            _timer?.Dispose();
            SaveUserPropLog();
            SaveUserPropCaches();
        }

        #endregion
        
    }
}