using dataladder.Data;
using SampleServiceNamespace;
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;
using TriggerDemoGui.ApiWebService;

namespace TriggerDemoGui
{
    public partial class Form1 : Form
    {
        //static string _connectionString = $"Server=(localdb)\\MSSQLlocaldb;Database=TriggerGuiDemo;Trusted_Connection=True;";//"(localdb)\MSSQLlocaldb"; 
        private string _connectionString;
        private string _holdingName;
        private string _masterName;
        private string _resultName;

        private bool _polling = false;
        private string loadedState = "";
        private string loadedName = "";
        private int loadedId = -1;
        private StateOfDemo _state = StateOfDemo.Wait;

        private DataTable _holdingTable;
        private DataTable _resultsTable;
        private DataTable _masterTable;

        public Form1()
        {
            InitializeComponent();
            Text += $" {ProductInfo.VersionApi} ({ProductInfo.Version})";

            _connectionString = Properties.Settings.Default.ConnectionString;
            _holdingName = Properties.Settings.Default.HoldingTableName;
            _masterName = Properties.Settings.Default.MasterTableName;
            _resultName = Properties.Settings.Default.ResultTableName;
        }
        

        private void InsertButton_Click(object sender, EventArgs e)
        {
            textBox3.Clear();
            Application.DoEvents();

            var state = textBox1.Text;
            var name = textBox2.Text;
            
            if (string.IsNullOrEmpty(state))
            {
                textBox3.AppendText("  'State' field is empty" + Environment.NewLine, Color.Red);
                return;
            }
            if (string.IsNullOrEmpty(name))
            {
                textBox3.AppendText("  'ContactName' field is empty" + Environment.NewLine, Color.Red);
                return;
            }

            textBox3.AppendText($"  Start inserted '{state}',  '{name}'  record into Holding Table " + Environment.NewLine);

            string error;
            InsertRecord(_holdingName, new string[] { "[State]", "[ContactName]" }, new string[] { state, name }, out error);
            Application.DoEvents();

            if (!string.IsNullOrEmpty(error))
            {
                textBox3.AppendText("  Error happened: " + error + Environment.NewLine + Environment.NewLine, Color.Red);
                _polling = false;
            }
            else
            {
                textBox3.AppendText($"  Record was inserted succesfully" + Environment.NewLine);
                _polling = true;

                _state = StateOfDemo.Inserting;
                loadedState = state;
                loadedName = name;
            }
        }

        //not used, for debuging
        private void InsertButton_Click2(object sender, EventArgs e)
        {
            textBox3.Clear();
            Application.DoEvents();

            var state = textBox1.Text;
            var name = textBox2.Text;

            using (TriggerDemoGui.ApiWebService.DmeApiWebServiceClient client = new TriggerDemoGui.ApiWebService.DmeApiWebServiceClient())
            {
                try
                {
                    string res = client.MatchAndInsertSync("TriggerGuiDemo", 642, new string[] { "wwww", "yohoho" });
                    textBox3.AppendText(res, Color.Blue);
                }
                catch (Exception ex)
                {
                    textBox3.AppendText("Res : " + ex.Message + Environment.NewLine, Color.Red);
                    textBox3.AppendText(ex.StackTrace + Environment.NewLine + Environment.NewLine);
                }
            }
        }


        public bool InsertRecord(string tableName, string[] TableFieldNames, string[] values, out string error)
        {
            bool result = false;
            error = "";
            try
            {
                StringBuilder sb = new StringBuilder();
                sb.Append("insert into ");
                sb.AppendLine(tableName);
                sb.AppendLine("(");
                for (int i = 0; i < TableFieldNames.Length; i++) // last field is ID, doesn't used in insert operation
                {
                    sb.Append(TableFieldNames[i]);
                    if (i < TableFieldNames.Length - 1)
                    {
                        sb.AppendLine(",");
                    }
                    else
                    {
                        sb.AppendLine("");
                    }
                }
                sb.AppendLine(")");
                sb.AppendLine("values");
                sb.AppendLine("(");
                for (int i = 0; i < TableFieldNames.Length; i++)
                {
                    //if (tableFieldQuotes[i])
                    {
                        sb.Append("'");
                    }
                    sb.Append(values[i]);
                    //if (tableFieldQuotes[i])
                    {
                        sb.Append("'");
                    }
                    if (i < TableFieldNames.Length - 1)
                    {
                        sb.AppendLine(",");
                    }
                    else
                    {
                        sb.AppendLine("");
                    }
                }
                sb.AppendLine(");");
                executeCmd(sb.ToString());
                //executeCmd($"insert into {tableName} (lastname) values ('{values[0]}')");
            }
            catch (Exception ex)
            {
                error = ex.Message;
            }
            return result;
        }

        private DataTable executeCmd(string cmd)
        {
            DataTable res = null;
            DbHelper dbHelper = new SqlDbHelper(_connectionString);

            String error;
            dbHelper.Connect(out error);
            res = dbHelper.SelectData(cmd);
            dbHelper.Disconnect();
            return res;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            LoadTableAsync();
        }

        private async Task LoadTableAsync()
        {
            int shownIndex;
            SqlLoader loader = new SqlLoader();

            _holdingTable = await loader.GetDataTableAsync(_connectionString, _holdingName);
            shownIndex = dataGridView1.FirstDisplayedScrollingRowIndex;
            dataGridView1.DataSource = _holdingTable;
            if (shownIndex != -1 )
                dataGridView1.FirstDisplayedScrollingRowIndex = shownIndex;

            _resultsTable = await loader.GetDataTableAsync(_connectionString, _resultName);
            shownIndex = dataGridView2.FirstDisplayedScrollingRowIndex;
            dataGridView2.DataSource = _resultsTable;
            if (shownIndex != -1)
                dataGridView2.FirstDisplayedScrollingRowIndex = shownIndex;

            _masterTable = await loader.GetDataTableAsync(_connectionString, _masterName);
            shownIndex = dataGridView3.FirstDisplayedScrollingRowIndex;
            dataGridView3.DataSource = _masterTable;
            if (shownIndex != -1)
                dataGridView3.FirstDisplayedScrollingRowIndex = shownIndex;
        }

        
        private void polling_Tick(object sender, EventArgs e)
        {
            if (_polling)
            {
                switch(_state)
                {
                    case StateOfDemo.Wait:
                        break;
                    case StateOfDemo.Inserting:
                        int shownIndex;
                        SqlLoader loader = new SqlLoader();
                        int cnt = _holdingTable?.Rows.Count??0;
                        var tableH = loader.GetDataTable(_connectionString, _holdingName);
                        if (cnt != tableH.Rows.Count)
                        {
                            shownIndex = dataGridView1.FirstDisplayedScrollingRowIndex;
                            dataGridView1.DataSource = tableH;
                            _holdingTable = tableH;
                            if (shownIndex != -1)
                                dataGridView1.FirstDisplayedScrollingRowIndex = shownIndex;
                        }
                        for (int i = tableH.Rows.Count - 1; i >=0 ; i--)
                        {
                            if (tableH.Rows[i]["State"].Equals(loadedState) && tableH.Rows[i]["ContactName"].Equals(loadedName))
                            {
                                if (tableH.Rows[i]["Id"] != null)
                                    if (tableH.Rows[i]["Id"] is Int32 tmp)
                                    {
                                        loadedId = tmp;
                                        _state = StateOfDemo.Inserted;
                                        textBox3.AppendText($"  Record was succesfully added in Holding Table" + Environment.NewLine);
                                        textBox3.AppendText($"- Trigger  'SendToMatchAfterInserting'  was fired" + Environment.NewLine, Color.RoyalBlue);
                                        break;
                                    }
                            }
                        }
                        break;
                    case StateOfDemo.Inserted:
                        loader = new SqlLoader();
                        cnt = _resultsTable?.Rows.Count??0;
                        tableH = loader.GetDataTable(_connectionString, _resultName);
                        //if (cnt != tableH.Rows.Count)
                        {
                            shownIndex = dataGridView2.FirstDisplayedScrollingRowIndex;
                            dataGridView2.DataSource = tableH;
                            _resultsTable = tableH;
                            if (shownIndex != -1)
                                dataGridView2.FirstDisplayedScrollingRowIndex = shownIndex;
                        }
                        int duplicates = -1;
                        int strongDuplicates = -1;
                        for (int i = tableH.Rows.Count - 1; i >= 0; i--)
                        {
                            if (tableH.Rows[i]["HoldingId"].Equals(loadedId))
                            {
                                if (tableH.Rows[i]["StrongDuplicate"] != null)
                                    if (tableH.Rows[i]["StrongDuplicate"] is Int32 tmp)
                                    {
                                        strongDuplicates = tmp;
                                    }
                                if (tableH.Rows[i]["Duplicate"] != null)
                                    if (tableH.Rows[i]["Duplicate"] is Int32 tmp)
                                    {
                                        duplicates = tmp;
                                    }
                                if (duplicates!= -1 && strongDuplicates != -1)
                                {
                                    textBox3.AppendText($"  Matching ended. Results were updated in Dupplicate Check Table" + Environment.NewLine);
                                    textBox3.AppendText($"- Trigger 'CopyUniqeRecordsInMasterTable' was fired" + Environment.NewLine, Color.RoyalBlue);
                                    if (strongDuplicates > 0)
                                    {
                                        _state = StateOfDemo.RecordRejected;
                                        textBox3.AppendText($"  Copying in Master Table was rejected, because there are strong duplicates " + Environment.NewLine);
                                        //break;
                                    }
                                    else
                                    {
                                        _state = StateOfDemo.ResultUpdated;
                                        textBox3.AppendText($"  Copying in Master Table was accepted" + Environment.NewLine);
                                        //break;
                                    }
                                }
                                break;
                            }
                        }

                        break;
                    case StateOfDemo.ResultRowCreated:
                        break;
                    case StateOfDemo.SendToMatching:
                        break;
                    case StateOfDemo.InMasterInserted:
                        break;

                    case StateOfDemo.RecordRejected:
                    case StateOfDemo.ResultUpdated:
                        loader = new SqlLoader();
                        cnt = _resultsTable?.Rows.Count??0;
                        tableH = loader.GetDataTable(_connectionString, _masterName);
                        if (cnt != tableH.Rows.Count)
                        {
                            shownIndex = dataGridView3.FirstDisplayedScrollingRowIndex;
                            dataGridView3.DataSource = tableH;
                            _resultsTable = tableH;
                            if (shownIndex != -1)
                                dataGridView3.FirstDisplayedScrollingRowIndex = shownIndex;
                        }

                        for (int i = tableH.Rows.Count - 1; i >= 0; i--)
                        {
                            if (tableH.Rows[i]["HoldingId"].Equals(loadedId))
                            {
                                _state = StateOfDemo.Wait;
                                _polling = false;
                                textBox3.AppendText($"  The record was copied into Master Table" + Environment.NewLine);
                                textBox3.AppendText($"- Trigger 'AddToCachedTable' was fired" + Environment.NewLine, Color.RoyalBlue);
                                break;
                            }
                        }
                        if (_state == StateOfDemo.RecordRejected)
                        {
                            _state = StateOfDemo.Wait;
                            _polling = false;
                        }
                        break;
                }
            }
        }



        private enum StateOfDemo
        {
            Wait,
            Inserting,
            Inserted,
            ResultRowCreated,
            SendToMatching,
            ResultUpdated,
            InMasterInserted,
            RecordRejected,
        }

        private void button2_Click(object sender, EventArgs e)
        {
            CheckVersion();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            InitService();
        }

        private void button4_Click(object sender, EventArgs e)
        {
            CheckDatabaseConnectionString();
        }

        private void CheckVersion()
        {
            textBox3.AppendText("Trying to connect with web service, and get version of service ..." + Environment.NewLine);
            Application.DoEvents();
            using (TriggerDemoGui.ApiWebService.DmeApiWebServiceClient client = new ApiWebService.DmeApiWebServiceClient())
            {
                try
                {
                    textBox3.AppendText("Web service version: " + client.GetVersion() + Environment.NewLine, Color.Green);
                }
                catch (Exception ex)
                {
                    textBox3.AppendText("Get service error : " + ex.Message + Environment.NewLine, Color.Red);
                    textBox3.AppendText(ex.StackTrace + Environment.NewLine + Environment.NewLine);
                }
            }
        }

        private void InitService()
        {
            textBox3.AppendText("Wait! Web service initializing  ..." + Environment.NewLine);
            Application.DoEvents();
            using (TriggerDemoGui.ApiWebService.DmeApiWebServiceClient client = new ApiWebService.DmeApiWebServiceClient())
            {
                try
                {
                    client.Init();
                    textBox3.AppendText("Web service initialized." + Environment.NewLine, Color.Green);
                }
                catch (Exception ex)
                {
                    textBox3.AppendText("Get Init error : " + ex.Message + Environment.NewLine, Color.Red);
                    textBox3.AppendText(ex.StackTrace + Environment.NewLine + Environment.NewLine);
                }
            }
        }

        private void CheckDatabaseConnectionString()
        {
            textBox3.AppendText("Trying to check database connection string ..." + Environment.NewLine);
            Application.DoEvents();
            SqlLoader loader = new SqlLoader();
            if (loader.CheckConnectionString(_connectionString, out string error))
            {
                textBox3.AppendText("DataBase connection is checked." + Environment.NewLine, Color.Green);
            }
            else
            {
                textBox3.AppendText($"Connection error ({_connectionString}): " + error + Environment.NewLine, Color.Red);
            }
        }
        
        private void Form1_Shown(object sender, EventArgs e)
        {
            CheckDatabaseConnectionString();
            Application.DoEvents();
            CheckVersion();
            Application.DoEvents();
            InitService();
            //Application.DoEvents();
            //GetErrors();
            Application.DoEvents();
            GetProjects();

        }

        private void button5_Click(object sender, EventArgs e)
        {
            textBox3.AppendText("Web service reinitializing  ..." + Environment.NewLine);
            Application.DoEvents();
            using (TriggerDemoGui.ApiWebService.DmeApiWebServiceClient client = new ApiWebService.DmeApiWebServiceClient())
            {
                try
                {
                    client.ReInit();
                    textBox3.AppendText("Web service reinitialized." + Environment.NewLine, Color.Green);
                }
                catch (Exception ex)
                {
                    textBox3.AppendText("Get Reinit error : " + ex.Message + Environment.NewLine, Color.Red);
                    textBox3.AppendText(ex.StackTrace + Environment.NewLine + Environment.NewLine);
                }
            }
        }

        private void button6_Click(object sender, EventArgs e)
        {
            GetErrors();
        }

        private void GetErrors()
        {
            textBox3.AppendText("Get web service errors  ...." + Environment.NewLine);
            Application.DoEvents();
            using (TriggerDemoGui.ApiWebService.DmeApiWebServiceClient client = new ApiWebService.DmeApiWebServiceClient())
            {
                try
                {
                    if (client == null)
                        textBox3.AppendText("client null" + Environment.NewLine);
                    //string[] pathes = client.GetPathes();
                    //if (pathes != null)
                    //{
                    //    foreach (var er in pathes)
                    //    {
                    //        textBox3.AppendText(er + Environment.NewLine);
                    //    }
                    //}
                    //else
                    //{
                    //    textBox3.AppendText("pathes null" + Environment.NewLine);
                    //}

                    string[] errors = (client.GetErors().Where(s => !((s??"").Equals(string.Empty)))??new string[0]).ToArray();

                    if (errors.Length > 0)
                    {
                        textBox3.AppendText("List of errors:" + Environment.NewLine, Color.Green);
                        foreach (var er in errors)
                        {
                            textBox3.AppendText(er + Environment.NewLine);
                        }
                        textBox3.AppendText("." + Environment.NewLine, Color.Green);
                    }
                    else
                    {
                        textBox3.AppendText("Service doesn't have errors " + Environment.NewLine, Color.Green);
                    }
                }
                catch (Exception ex)
                {
                    textBox3.AppendText("Error happened : " + ex.Message + Environment.NewLine, Color.Red);
                    textBox3.AppendText(ex.StackTrace + Environment.NewLine + Environment.NewLine);
                }
            }
        }

        private void button7_Click(object sender, EventArgs e)
        {
            GetProjects();
        }

        private void GetProjects()
        {
            textBox3.AppendText("Get web service loaded projects  ..." + Environment.NewLine);
            Application.DoEvents();
            using (TriggerDemoGui.ApiWebService.DmeApiWebServiceClient client = new ApiWebService.DmeApiWebServiceClient())
            {
                try
                {
                    string[] projects = client.GetLoadedProjects();
                    if (projects.Length > 0)
                    {
                        textBox3.AppendText("List of projects:" + Environment.NewLine, Color.Green);
                        foreach (var pj in projects)
                        {
                            textBox3.AppendText(pj + Environment.NewLine);
                        }
                    }
                    else
                    {
                        textBox3.AppendText("Service doesn't have loaded projects " + Environment.NewLine, Color.Green);
                    }
                }
                catch (Exception ex)
                {
                    textBox3.AppendText("Error happened : " + ex.Message + Environment.NewLine, Color.Red);
                    textBox3.AppendText(ex.StackTrace + Environment.NewLine + Environment.NewLine);
                }
            }
        }
    }

    public static class RichTextBoxExtensions
    {
        public static void AppendText(this RichTextBox box, string text, Color color)
        {
            box.SelectionStart = box.TextLength;
            box.SelectionLength = 0;
            Font font = box.SelectionFont;
            box.SelectionFont = new Font(font, FontStyle.Bold);

            box.SelectionColor = color;
            box.AppendText(text);
            box.SelectionColor = box.ForeColor;
        }
    }

}
