using MongoDB.Bson;
using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace lolDataSimulation
{
    /// <summary>
    /// 시뮬레이션으로 게임데이터를 만들기위한 프로그램
    /// 
    /// 좀 쓰다 버릴줄알고 발로짰다. 이렇게 많이 쓸줄 알았으면 여기에 목숨을 걸어야했는데..
    /// 
    /// </summary>
    public partial class SimulationForm : Form
    {
        public SimulationForm()
        {
            InitializeComponent();

            updateTimer.Tick += timeup;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            var mEventDataBaseTarget = mDBClient.GetDatabase("datalol");

            mEventDataBaseTarget.GetCollection<BsonDocument>("champ_select").DeleteMany("{ RequestGameID : '" + textBox1.Text + "' }");

            textBox2.Text = (-1000).ToString();

        }

        private void btnBanPickNect_Click(object sender, EventArgs e)
        {
            banPickNext();
        }
        

        //MongoClient mDBClient = new MongoClient("mongodb://root:veryhardpassword123@203.251.148.27:50002");
        MongoClient mDBClient = new MongoClient("mongodb://root:veryhardpassword123@211.42.188.8:50003");
        //MongoClient mDBClient = new MongoClient("mongodb://root:veryhardpassword123@localhost:60001");

        void banPickNext()
        {



            var mEventDataBaseSeed = mDBClient.GetDatabase("data_lol_test_seed");

            var filter = Builders<BsonDocument>.Filter.And(
                Builders<BsonDocument>.Filter.Eq("RequestGameID", textBox1.Text),
                Builders<BsonDocument>.Filter.Eq("sequenceIndex", Convert.ToInt32(textBox2.Text))
                );

            var projection = Builders<BsonDocument>.Projection
                .Exclude("_id")
                .Include("RequestGameID")
                .Include("sequenceIndex")
                .Include("eventDocument");

            List<BsonDocument> documents = mEventDataBaseSeed.GetCollection<BsonDocument>("champ_select")
                .Find(filter)
                .SortByDescending(x => x["sequenceIndex"])
                .Project(projection)
                .Limit(1)
                .ToList();

            if (documents.Count == 0)
            {
                MessageBox.Show("업데이트할 데이터가 없습니다.");
                return;
            }

            var mEventDataBaseTarget = mDBClient.GetDatabase("datalol");

            mEventDataBaseTarget.GetCollection<BsonDocument>("champ_select").InsertOne(documents.Last());

            textBox2.Text = (Convert.ToInt32(textBox2.Text) + 1).ToString();

        }


        Timer updateTimer = new Timer();
        private void button3_Click(object sender, EventArgs e)
        {
            updateTimer.Interval = 1000;

            updateTimer.Start();
           
        }

        void timeup(object o, EventArgs e)
        {
            if (Convert.ToInt32(numericUpDown2.Value) == 59)
            {
                numericUpDown1.Value += 1;
                numericUpDown2.Value = 0;
            }
            else
            {
                numericUpDown2.Value += 1;
            }
        }
        string[] bufUpdateCollectionsName = { "stats_update", "epic_monster_kill", "building_destroyed", "turret_plate_destroyed", "queued_dragon_info" };

        void liveDataUpdateWork()
        {
            var mEventDataBaseSeed = mDBClient.GetDatabase("data_lol_test_seed");

            var mEventDataBaseTarget = mDBClient.GetDatabase("datalol");

            int calculatedTime = 0;

            calculatedTime += Convert.ToInt32(numericUpDown1.Value) * 60 * 1000;

            calculatedTime += Convert.ToInt32(numericUpDown2.Value) * 1000;

            Dictionary<string, List<WriteModel<BsonValue>>> bufDataTable = new Dictionary<string, List<WriteModel<BsonValue>>>();


            var subFilter = MongoDB.Bson.Serialization.BsonSerializer.Deserialize<BsonDocument>("{'eventDocument.gameTime' : {$lt : " + calculatedTime + " }}");

            var filter = Builders<BsonDocument>.Filter.And(
                Builders<BsonDocument>.Filter.Eq("RequestGameID", textBox1.Text),
                subFilter
                );

            foreach (string item in bufUpdateCollectionsName)
            {

              
                var projection = Builders<BsonDocument>.Projection
                    .Exclude("_id")
                    .Include("RequestGameID")
                    .Include("sequenceIndex")
                    .Include("eventDocument");

                List<BsonDocument> documents = mEventDataBaseSeed.GetCollection<BsonDocument>(item)
                    .Find(filter)
                    .SortByDescending(x => x["sequenceIndex"])
                    .Project(projection)
                    .Limit(1)
                    .ToList();


                if (documents.Count == 0)
                {
                    continue;
                }

                BsonDocument bufUpdateValue = documents[0].AsBsonDocument;

                string bufStatus = bufUpdateValue["eventDocument"]["rfc461Schema"].ToString();



                var gameFilter = Builders<BsonValue>.Filter.Eq(x => x["RequestGameID"], textBox1.Text);

                var sequanceFilter = Builders<BsonValue>.Filter.Eq(x => x["sequenceIndex"], documents[0]["sequenceIndex"]);

                var Parentfilter = Builders<BsonValue>.Filter.And(gameFilter, sequanceFilter);

                
                UpdateOneModel<BsonValue> updateRaw = new UpdateOneModel<BsonValue>(
                    Parentfilter,
                    Builders<BsonValue>.Update.Set(x => x["eventDocument"], bufUpdateValue["eventDocument"])
                    )
                { IsUpsert = true };

                if (!bufDataTable.ContainsKey(bufStatus))
                {
                    bufDataTable.Add(bufStatus, new List<WriteModel<BsonValue>>());
                }

             
                if (item == "stats_update")
                {

                    Console.WriteLine(bufUpdateValue["eventDocument"]["gameTime"].ToString());
                    

                }

                bufDataTable[bufStatus].Add(updateRaw);

            }


            foreach (var item in bufDataTable)
            {
              

                mEventDataBaseTarget.GetCollection<BsonValue>(item.Key)
                    .BulkWriteAsync(item.Value);
            }

        }

        private void numericUpDown2_ValueChanged(object sender, EventArgs e)
        {
            liveDataUpdateWork();
        }

        private void btnClearGameData_Click(object sender, EventArgs e)
        {

            var mEventDataBaseTarget = mDBClient.GetDatabase("datalol");
            foreach (string item in bufUpdateCollectionsName)
            {
                mEventDataBaseTarget.GetCollection<BsonValue>(item)
                   .DeleteMany(x => true);
            }
            
        }

        private void btnAutoplayEnd_Click(object sender, EventArgs e)
        {
            updateTimer.Stop();
        }

        private void btnSyncGameData_Click(object sender, EventArgs e)
        {
            var mEventDataBaseTarget = mDBClient.GetDatabase("datalol");
     

            var mEventDataBaseSeed = mDBClient.GetDatabase("data_lol_test_seed");


            int calculatedTime = 0;

            calculatedTime += Convert.ToInt32(numericUpDown1.Value) * 60 * 1000;

            calculatedTime += Convert.ToInt32(numericUpDown2.Value) * 1000;

            Dictionary<string, List<WriteModel<BsonValue>>> bufDataTable = new Dictionary<string, List<WriteModel<BsonValue>>>();


            var subFilter = MongoDB.Bson.Serialization.BsonSerializer.Deserialize<BsonDocument>("{'eventDocument.gameTime' : {$lt : " + calculatedTime + " }}");

            var filter = Builders<BsonDocument>.Filter.And(
                Builders<BsonDocument>.Filter.Eq("RequestGameID", textBox1.Text),
                subFilter
                );

            foreach (string item in bufUpdateCollectionsName)
            {


                var projection = Builders<BsonDocument>.Projection
                    .Exclude("_id")
                    .Include("RequestGameID")
                    .Include("sequenceIndex")
                    .Include("eventDocument");

                List<BsonDocument> documents = mEventDataBaseSeed.GetCollection<BsonDocument>(item)
                    .Find(filter)
                    //.SortByDescending(x => x["sequenceIndex"])
                    .Project(projection)
                    .ToList();


                if (documents.Count == 0)
                {
                    continue;
                }

                //BsonDocument bufUpdateValue = documents[0].AsBsonDocument;


                foreach (BsonDocument itemd in documents)
                {

                string bufStatus = itemd["eventDocument"]["rfc461Schema"].ToString();

                var gameFilter = Builders<BsonValue>.Filter.Eq(x => x["RequestGameID"], textBox1.Text);

                var sequanceFilter = Builders<BsonValue>.Filter.Eq(x => x["sequenceIndex"], itemd["sequenceIndex"]);

                var Parentfilter = Builders<BsonValue>.Filter.And(gameFilter, sequanceFilter);


                UpdateOneModel<BsonValue> updateRaw = new UpdateOneModel<BsonValue>(
                    Parentfilter,
                    Builders<BsonValue>.Update.Set(x => x["eventDocument"], itemd["eventDocument"])
                    )
                { IsUpsert = true };

                if (!bufDataTable.ContainsKey(bufStatus))
                {
                    bufDataTable.Add(bufStatus, new List<WriteModel<BsonValue>>());
                }

                if (item == "stats_update")
                {
                    Console.WriteLine(itemd["eventDocument"]["gameTime"].ToString());
                }

                bufDataTable[bufStatus].Add(updateRaw);

                }
            }


            foreach (var item in bufDataTable)
            {


                mEventDataBaseTarget.GetCollection<BsonValue>(item.Key)
                    .BulkWriteAsync(item.Value);
            }




        }
    }
}
