using MongoDB.Bson;
using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LolDataRequestLib.ResponseData
{
    internal class 팟지선수 : AResponseData
    {

        private int nullToZero(string value)
        {
            try
            {
                return Convert.ToInt32(value);
            }
            catch(Exception e)
            {
                return 0;
            }
        }
        private double nullToZeroD(string value)
        {
            try
            {
                return Convert.ToDouble(value);
            }
            catch (Exception e)
            {
                return 0;
            }
        }

        protected override DataTable buildDataForResponse(BsonDocument recvDocument)
        {
            
            DataTable 팟지데이터테이블 = new DataTable();

            팟지데이터테이블.TableName = DBDefine.요청데이터분류.팟지.ToString();

            //선수관련
            팟지데이터테이블.Columns.Add("게임시간");
            팟지데이터테이블.Columns.Add("누적된분");
            팟지데이터테이블.Columns.Add("팀구분");
            팟지데이터테이블.Columns.Add("선수아이디");
            팟지데이터테이블.Columns.Add("챔피언");

            //KDA
            팟지데이터테이블.Columns.Add("킬");
            팟지데이터테이블.Columns.Add("데스");
            팟지데이터테이블.Columns.Add("어시스트");

            //데미지관련
            팟지데이터테이블.Columns.Add("가한데미지");
            팟지데이터테이블.Columns.Add("받은데미지");
            팟지데이터테이블.Columns.Add("팀원에게준힐량");
            팟지데이터테이블.Columns.Add("팀원의데미지를막아낸실드량");

            //분당데미지관련
            팟지데이터테이블.Columns.Add("분당가한데미지");
            팟지데이터테이블.Columns.Add("분당받은데미지");
            팟지데이터테이블.Columns.Add("분당팀원에게준힐량");
            팟지데이터테이블.Columns.Add("분당팀원의데미지를막아낸실드량");

            ///스코어관련
            팟지데이터테이블.Columns.Add("크립스코어");
            팟지데이터테이블.Columns.Add("경험치");
            팟지데이터테이블.Columns.Add("분당크립스코어");
            팟지데이터테이블.Columns.Add("비전스코어");
            팟지데이터테이블.Columns.Add("설치한와드수");
            팟지데이터테이블.Columns.Add("부순와드수");
            팟지데이터테이블.Columns.Add("골드획득량");
            팟지데이터테이블.Columns.Add("분당골드획득량");

            //CC
            팟지데이터테이블.Columns.Add("군중제어점수");
            팟지데이터테이블.Columns.Add("다른챔피언에CC기를건시간");

            //추가
            팟지데이터테이블.Columns.Add("킬관여율");
            팟지데이터테이블.Columns.Add("골드당데미지");
            팟지데이터테이블.Columns.Add("팀내데미지비중");

            //2022 데이터 추가 중립크립스코어
            팟지데이터테이블.Columns.Add("라인크립스코어");
            팟지데이터테이블.Columns.Add("정글크립스코어");

            //2022 데이터 추가 현상금
            팟지데이터테이블.Columns.Add("현재현상금");


            if (m팟지데이터들.Count == 0 || m팀데이터들.Count == 0)
            {
                return 팟지데이터테이블;
            }

            Dictionary<int, int> 블루팀_킬_수 = new Dictionary<int, int>();
            Dictionary<int, int> 퍼플팀_킬_수 = new Dictionary<int, int>();


            foreach (BsonDocument item in m팀데이터들)
            {
             
                BsonArray bufTeamArray = item.Values.Last().AsBsonArray;

                foreach (BsonValue itemTeam in bufTeamArray)
                {
                    if (itemTeam["teamID"].ToInt32() == (int)DBDefine.팀구분.블루)
                    { 
                        블루팀_킬_수.Add(Convert.ToInt32(item.Names.Last()), nullToZero(itemTeam["championsKills"].ToString()));
                    }
                    else
                    {
                        퍼플팀_킬_수.Add(Convert.ToInt32(item.Names.Last()), nullToZero(itemTeam["championsKills"].ToString()));
                    }
                }

               
            }


            Dictionary<int, double> 블루팀_데미지_합 = new Dictionary<int, double>();
            Dictionary<int, double> 퍼플팀_데미지_합 = new Dictionary<int, double>();



            foreach (BsonDocument item in m팟지데이터들)
            {
                int gameTime = Convert.ToInt32(item.Names.Last());

                double gameTimeMin = Convert.ToDouble(gameTime) / 60.0;

                BsonArray bufPlayersData = item.Values.Last().AsBsonArray;

                foreach (var itemPlayer in bufPlayersData)
                {
                    DataRow bufRow = 팟지데이터테이블.NewRow();

                    bufRow["게임시간"] = gameTime;
                    bufRow["누적된분"] = gameTimeMin;
                    bufRow["팀구분"] = (DBDefine.팀구분)itemPlayer["teamID"].ToInt32();
                    bufRow["선수아이디"] = itemPlayer["playerName"].ToString();
                    bufRow["챔피언"] = itemPlayer["championName"].ToString();

                    //스텟이 아닌 선수정보에 있는 것들
                    bufRow["경험치"] = itemPlayer["XP"].ToInt32();
                    bufRow["골드획득량"] = itemPlayer["totalGold"].ToInt32();
                    bufRow["분당골드획득량"] = itemPlayer["totalGold"].ToDouble() / (gameTimeMin);
                    bufRow["현재현상금"] = itemPlayer["shutdownValue"].ToInt32();


                    BsonArray bufStats = itemPlayer["stats"].AsBsonArray;

                    foreach (BsonValue itemStats in bufStats)
                    {

                        switch (itemStats["name"].ToString())
                        {

                            case "CHAMPIONS_KILLED":
                                try { bufRow["킬"] = itemStats["value"].ToString(); }
                                catch (Exception ex) { bufRow["킬"] = "0"; }
                                
                                break;

                            case "NUM_DEATHS":
                                try { bufRow["데스"] = itemStats["value"].ToString(); }
                                catch (Exception ex) { bufRow["데스"] = "0"; } 
                                break;

                            case "ASSISTS":
                                try { bufRow["어시스트"] = itemStats["value"].ToString(); }
                                catch (Exception ex) { bufRow["어시스트"] = "0"; } 
                                break;

                            //데미지관련
                            case "TOTAL_DAMAGE_DEALT_TO_CHAMPIONS":
                                bufRow["가한데미지"] = itemStats["value"].ToInt32();
                                bufRow["분당가한데미지"] = itemStats["value"].ToDouble() / (gameTimeMin);
                                bufRow["골드당데미지"] = itemStats["value"].ToDouble() / itemPlayer["totalGold"].ToDouble();

                                if ((DBDefine.팀구분)itemPlayer["teamID"].ToInt32() == DBDefine.팀구분.블루)
                                {
                                    if (!블루팀_데미지_합.ContainsKey(Convert.ToInt32(bufRow["게임시간"])))
                                    {
                                        블루팀_데미지_합.Add(Convert.ToInt32(bufRow["게임시간"]), itemStats["value"].ToInt32());
                                    }
                                    else
                                    {
                                        블루팀_데미지_합[Convert.ToInt32(bufRow["게임시간"])] += itemStats["value"].ToInt32();
                                    }

                                }
                                else
                                {
                                    if (!퍼플팀_데미지_합.ContainsKey(Convert.ToInt32(bufRow["게임시간"])))
                                    {
                                        퍼플팀_데미지_합.Add(Convert.ToInt32(bufRow["게임시간"]), itemStats["value"].ToInt32());
                                    }
                                    else
                                    {
                                        퍼플팀_데미지_합[Convert.ToInt32(bufRow["게임시간"])] += itemStats["value"].ToInt32();
                                    }
                                }
                                
                                break;

                            case "TOTAL_DAMAGE_TAKEN":
                                bufRow["받은데미지"] = itemStats["value"].ToInt32();
                                bufRow["분당받은데미지"] = itemStats["value"].ToDouble() / (gameTimeMin);
                                break;

                            case "TOTAL_HEAL_ON_TEAMMATES":
                                 bufRow["팀원에게준힐량"] = itemStats["value"].ToInt32();
                                bufRow["분당팀원에게준힐량"] = itemStats["value"].ToDouble() / (gameTimeMin);
                                break;

                            case "TOTAL_DAMAGE_SHIELDED_ON_TEAMMATES":
                                bufRow["팀원의데미지를막아낸실드량"] = itemStats["value"].ToInt32();
                                bufRow["분당팀원의데미지를막아낸실드량"] = itemStats["value"].ToDouble() / (gameTimeMin);
                                break;

                            ///스코어관련
                            case "MINIONS_KILLED":
                                bufRow["라인크립스코어"] = nullToZero(itemStats["value"].ToString());
                                //bufRow["분당크립스코어수급량"] = itemStats["value"].ToDouble()/(gameTimeMin);
                                break;

                            case "NEUTRAL_MINIONS_KILLED":
                                bufRow["정글크립스코어"] = itemStats["value"].ToInt32();
                                break;


                            case "VISION_SCORE":
                                bufRow["비전스코어"] = itemStats["value"].ToInt32();
                                break;
                            case "WARD_PLACED":
                                bufRow["설치한와드수"] = itemStats["value"].ToString();
                                break;

                            case "WARD_KILLED":
                                bufRow["부순와드수"] = itemStats["value"].ToString();
                                break;

                            case "TOTAL_TIME_CROWD_CONTROL_DEALT":
                                bufRow["군중제어점수"] = itemStats["value"].ToString();
                                break;

                            case "TIME_CCING_OTHERS":
                                bufRow["다른챔피언에CC기를건시간"] = itemStats["value"].ToString();
                                break;
                        }

                    }

                    //bufRow["크립스코어"] = Convert.ToInt32(bufRow["라인크립스코어"]) + Convert.ToInt32(bufRow["정글크립스코어"]);
                    //bufRow["분당크립스코어"] = Convert.ToDouble(bufRow["크립스코어"]) / (gameTimeMin);

                    bufRow["크립스코어"] = nullToZero(bufRow["라인크립스코어"].ToString()) + nullToZero(bufRow["정글크립스코어"].ToString());
                    bufRow["분당크립스코어"] = nullToZeroD(bufRow["크립스코어"].ToString()) / (gameTimeMin);

                    팟지데이터테이블.Rows.Add(bufRow);

                }

            }

            foreach (DataRow bufRow in 팟지데이터테이블.Rows)
            {
                if (bufRow["팀구분"].ToString() == "블루")
                {
                    try
                    {
                        bufRow["팀내데미지비중"] = Convert.ToDouble(bufRow["가한데미지"]) / 블루팀_데미지_합[Convert.ToInt32(bufRow["게임시간"])] * 100.0;
                    }
                    catch(Exception ex)
                    {
                        bufRow["팀내데미지비중"] = "Err";
                    }
                    
                    try
                    {
                        
                        bufRow["킬관여율"] = (nullToZeroD(bufRow["킬"].ToString()) + nullToZeroD(bufRow["어시스트"].ToString())) / 블루팀_킬_수[Convert.ToInt32(bufRow["게임시간"])] * 100.0;
                    }
                    catch(Exception ex)
                    {
                        bufRow["킬관여율"] = "Err";
                    }
                }
                else
                {
                    try
                    {
                        bufRow["팀내데미지비중"] = Convert.ToDouble(bufRow["가한데미지"]) / 퍼플팀_데미지_합[Convert.ToInt32(bufRow["게임시간"])] * 100.0;
                    }
                    catch(Exception ex)
                    {
                        bufRow["팀내데미지비중"] = "Err";
                    }
                    
                    try
                    {
                        bufRow["킬관여율"] = (nullToZeroD(bufRow["킬"].ToString()) + nullToZeroD(bufRow["어시스트"].ToString())) / 퍼플팀_킬_수[Convert.ToInt32(bufRow["게임시간"])] * 100.0;
                    }
                    catch(Exception ex)
                    {
                        bufRow["킬관여율"] = "Err";
                    }
                }
            }


            팟지데이터테이블.Columns.Remove("게임시간");
            
            return 팟지데이터테이블;

        }

        List<BsonDocument> m팟지데이터들 = new List<BsonDocument>();

        List<BsonDocument> m팀데이터들 = new List<BsonDocument>();

        protected override BsonDocument getDataFromMongo()
        {
            //팟지데이터는 5분단위로 누적.
            //ex ~5 ~10 ~15 ~20 ~25 ~30... 마지막데이터는 0
            //맨 처음 전체데이터로 경기시간을 구한다음 시간으로 나눈다?

            if (DataManager.getInstance().경기데이터 == null)
            {
                return null;
            }
            int 경기시간 = DataManager.getInstance().경기데이터["gameTime"].ToInt32() / 1000;

            int 앞에서부터초 = 0;

            m팟지데이터들 = new List<BsonDocument>();

            m팀데이터들 = new List<BsonDocument>();

            while (경기시간 - 앞에서부터초 > 0)
            {

                앞에서부터초 += 5 * 60;

                BsonDocument rtnValue = new BsonDocument();

                //var subfilter1 = Builders<BsonDocument>.Filter.Eq("RequestGameID", DataManager.getInstance().mPlatformGameID);

                var subFilter2 = MongoDB.Bson.Serialization.BsonSerializer.Deserialize<BsonDocument>("{'eventDocument.gameTime' : {$lt : " + 앞에서부터초  * 1000 + " }}");

                var filter1 = Builders<BsonDocument>.Filter.And(subFilter2); //var filter1 = Builders<BsonDocument>.Filter.And(subfilter1, subFilter2);

                var projectionFilter = MongoDB.Bson.Serialization.BsonSerializer.Deserialize<BsonDocument>("{'eventDocument.participants' : 1, 'eventDocument.teams' : 1}");

                List<BsonDocument> documents = mEventDataBase.GetCollection<BsonDocument>("stats_update")
                    .Find(filter1)
                    .SortByDescending(x => x["sequenceIndex"])
                    .Limit(1)
                    .ToList();

                ///경기의 마지막정보는 경기시간으로 리턴.
                if (앞에서부터초 > 경기시간)
                {
                    rtnValue.Add(경기시간.ToString(), documents.Last()["eventDocument"]["participants"].AsBsonArray);
                }
                else
                {
                    rtnValue.Add(앞에서부터초.ToString(), documents.Last()["eventDocument"]["participants"].AsBsonArray);
                }
                

                m팟지데이터들.Add(rtnValue);


                rtnValue = new BsonDocument();

                if (앞에서부터초 > 경기시간)
                {
                    rtnValue.Add(경기시간.ToString(), documents.Last()["eventDocument"]["teams"].AsBsonArray);
                }
                else
                {
                    rtnValue.Add(앞에서부터초.ToString(), documents.Last()["eventDocument"]["teams"].AsBsonArray);
                }

                m팀데이터들.Add(rtnValue);

            }
         
            //구조를 위해 리턴은 하지만 이 상속클래스는 BsonDocument를 멤버변수 kv페어로 관리한다.
            return new BsonDocument();
        }
    }
}
