using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;

using C4IT.Logging;
using C4IT.DataHistoryProvider;

using static C4IT.Logging.cLogManager;

namespace C4IT_DataHistoryProvider_Test
{
    public partial class ctrlNexthink : UserControl
    {
        private cNxqlColumnsValidationResult ValidationResults = null;

        private bool isScanEnabled = false;
        private bool isColumnCheck = false;


        public ctrlNexthink()
        {
            InitializeComponent();

            webBrowserTableResult.DocumentText = "<HTML></HTML>";
        }

        private async void ctrlNexthink_Load(object sender, EventArgs e)
        {
            panelScanNext.Height = textBoxScanNext.Height;
            panelScanNext.Top = textBoxScanNext.Top;

            var _requestInfo = new cF4sdWebRequestInfo("ctrlNexthink_Load", null);
            await checkScanTimesAsync(_requestInfo, 1);
        }

        private void SetBrowserContent(string Content)
        {
            webBrowserTableResult.Navigate("about:blank");
            var doc = webBrowserTableResult.Document.OpenNew(true);
            if (string.IsNullOrWhiteSpace(Content))
                doc.Write("<HTML></HTML>");
            else
                doc.Write(Content);
            webBrowserTableResult.Refresh();
        }

        private async void buttonScanTableColumns_Click(object sender, EventArgs e)
        {
            MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
            try
            {
                Cursor = Cursors.WaitCursor;
                Program.mainForm.DisableAllTabPages(this);
                buttonScanTableColumns.Enabled = false;
                tabControlResult.SelectedIndex = 0;
                tabPageProtocol.Refresh();

                ctrlProtocolBox1.ClearMessages();
                treeViewValidationResult.Nodes.Clear();
                richTextBoxTableResult.Text = "";
                SetBrowserContent(null);

                var _requestInfo = new cF4sdWebRequestInfo("buttonScanTableColumns_Click", null);

                Program.Collector.CleanupUiMessageHandler();
                Program.Collector.ProcessUiMessage += ctrlProtocolBox1.ProcessMessage;

                var Validator = new cNxqlColumnValidator(Program.Collector);
                await Task.Run(async () =>
                {
                    try
                    {
                        await Validator.DoValidationAsync(_requestInfo, 1, CancellationToken.None).ConfigureAwait(false);
                    }
                    catch (Exception E)
                    {
                        LogException(E);
                    }
                });

                TreeNode firstNode = null;
                TreeNode firstErrorNode = null;
                treeViewValidationResult.Nodes.Clear();
                foreach (var Portal in Validator.ValidationResults.Values)
                {
                    var tn = new TreeNode($"{Portal.Portal.Name} ({Portal.Portal.Address})");
                    treeViewValidationResult.Nodes.Add(tn);

                    foreach (var Table in Portal.TableResults.Values)
                    {
                        var tn2 = new TreeNode($"{Table.Table.Name}")
                        {
                            Tag = Table
                        };
                        tn.Nodes.Add(tn2);
                        var isAllValid = true;
                        foreach (var Column in Table.ColumnResults.Values)
                        {
                            isAllValid &= Column.IsValid;
                            var sn = "";
                            if (!string.IsNullOrEmpty(Column.Column.SourceTable))
                                sn = $" ({Column.Column.SourceTable} {Column.Column.SourceName})";
                            if (Column.Column.SourceName != Column.Column.Name)
                                sn = $" ({Column.Column.SourceName})";
                            var tn3 = new TreeNode($"{Column.Column.Name}{sn}")
                            {
                                Tag = Column
                            };
                            tn2.Nodes.Add(tn3);
                            if (Column.IsValid)
                                tn3.ImageIndex = 0;
                            else
                            {
                                tn3.ImageIndex = 2;
                                if (firstErrorNode == null)
                                    firstErrorNode = tn2;
                            }
                            tn3.SelectedImageIndex = tn3.ImageIndex;
                        }
                        if (Table.IsValid)
                        {
                            if (isAllValid)
                                tn2.ImageIndex = 0;
                            else
                            {
                                tn2.ImageIndex = 1;
                                if (firstErrorNode == null)
                                    firstErrorNode = tn2;
                            }
                        }
                        else
                        {
                            tn2.ImageIndex = 2;
                            if (firstErrorNode == null)
                                firstErrorNode = tn2;
                        }
                        tn2.SelectedImageIndex = tn2.ImageIndex;

                        if (!isAllValid)
                            tn2.Expand();
                        else
                            tn2.Collapse();
                    }
                    tn.ImageIndex = -1;
                    tn.SelectedImageIndex = -1;
                    tn.Expand();
                    if (firstNode == null)
                        firstNode = tn;
                }

                if (firstNode != null)
                    firstNode.EnsureVisible();
                if (firstErrorNode != null)
                    firstErrorNode.EnsureVisible();

                ValidationResults = Validator.ValidationResults;
                isColumnCheck = true;

                tabControlResult.SelectedIndex = 1;
                tabPageQueryResult.Refresh();

                await checkScanTimesAsync(_requestInfo, 1);

            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                ctrlProtocolBox1.ProcessMessage("");
                this.Enabled = true;
                Program.mainForm.EnableAllTabPages();
                buttonScanTableColumns.Enabled = true;
                Cursor = Cursors.Default;
                if (CM != null) LogMethodEnd(CM);
            }
        }

        private void treeViewValidationResult_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if (treeViewValidationResult.SelectedNode?.Tag is cNxqlTableValidationResult TableResult)
            {
                richTextBoxTableResult.Text = TableResult.NXQL;
                SetBrowserContent(TableResult.ErrorMessage);
                return;
            }

            if (treeViewValidationResult.SelectedNode?.Tag is cNxqlColumnValidationResult ColumnResult)
            {
                richTextBoxTableResult.Text = ColumnResult.NXQL;
                SetBrowserContent(ColumnResult.ErrorMessage);
                return;
            }

            richTextBoxTableResult.Text = "";
            SetBrowserContent(null);
        }

        private async void buttonQueryData_Click(object sender, EventArgs e)
        {
            MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
            try
            {
                if (ValidationResults == null)
                    return;
                if (Program.Collector == null)
                    return;

                var _requestInfo = new cF4sdWebRequestInfo("buttonQueryData_Click", null);

                Cursor = Cursors.WaitCursor;

                ctrlProtocolBox1.ClearMessages();
                this.Enabled = false;
                SetBrowserContent(null);

                tabControlResult.SelectedIndex = 0;

                buttonQueryData.Enabled = false;
                buttonScanTableColumns.Enabled = false;
                buttonRemoveScan.Enabled = false;

                Program.mainForm.DisableAllTabPages(this);

                Program.Collector.CleanupUiMessageHandler();
                Program.Collector.ProcessUiMessage += ctrlProtocolBox1.ProcessMessage;

                if (Program.Collector.NxqlCollector != null)
                {
                    Program.Collector.NxqlCollector.LastValidationResults = ValidationResults;
                    Application.DoEvents();
                    await Program.Collector.NxqlCollector.DoScanAsync(true, false, _requestInfo, 1, CancellationToken.None, true);
                }

                await checkScanTimesAsync(_requestInfo, 1);
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                this.Enabled = true;
                Program.mainForm.EnableAllTabPages();
                Cursor = Cursors.Default;
                if (CM != null) LogMethodEnd(CM);
            }

        }

        private async Task checkScanTimesAsync(cF4sdWebRequestInfo requestInfo, int LogDeep)
        {
            MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
            if (cPerformanceLogger.IsActive && requestInfo != null) { if (CM == null) CM = MethodBase.GetCurrentMethod(); cPerformanceLogger.LogPerformanceStart(LogDeep, CM, requestInfo.id, requestInfo.created); }
            var _startTime = DateTime.UtcNow;

            try
            {
                var Col = Color.Transparent;
                textBoxScanLast.Text = "";
                textBoxScanNext.Text = "";

                isScanEnabled = false;
                if (Program.Collector != null)
                {
                    var scanInfo = await Program.Collector.NxqlCollector.GetScanTimeInfoAsync(requestInfo, LogDeep+1, CancellationToken.None);

                    if (scanInfo?.NextScan is DateTime nextScan)
                    {
                        textBoxScanNext.Text = nextScan.ToLocalTime().ToString();
                        if (scanInfo?.LastScan is DateTime lastScan)
                        {
                            textBoxScanLast.Text = lastScan.ToLocalTime().ToString();
                            if (nextScan >= lastScan)
                            {
                                Col = Color.Red;
                                isScanEnabled = true;
                            }
                            else
                                Col = Color.Green;
                        }
                        else
                        {
                            Col = Color.Red;
                            isScanEnabled = true;
                        }
                    }
                    else
                    {
                        Col = Color.Red;
                        isScanEnabled = true;
                        if (scanInfo?.LastScan is DateTime lastScan)
                            textBoxScanLast.Text = lastScan.ToLocalTime().ToString();
                    }

                }

                panelScanNext.BackColor = Col;
                buttonQueryData.Enabled = isScanEnabled && isColumnCheck;
                buttonRemoveScan.Enabled = isColumnCheck;

            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                if (cPerformanceLogger.IsActive && requestInfo != null) { cPerformanceLogger.LogPerformanceEnd(LogDeep, CM, requestInfo.id, requestInfo.created, _startTime); }
                if (CM != null) LogMethodEnd(CM);
            }
        }

        private async Task DoScanAsync(bool Rescan)
        {
            MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }

            if (Program.Collector == null)
                return;

            try
            {
                Cursor = Cursors.WaitCursor;

                ctrlProtocolBox1.ClearMessages();
                buttonQueryData.Enabled = false;
                buttonScanTableColumns.Enabled = false;
                buttonRemoveScan.Enabled = false;

                Program.mainForm.DisableAllTabPages(this);

                Program.Collector.CleanupUiMessageHandler();
                Program.Collector.ProcessUiMessage += ctrlProtocolBox1.ProcessMessage;
                var _requestInfo = new cF4sdWebRequestInfo("DoScanNexthink", null);
                await Program.Collector.NxqlCollector.DoScanAsync(true, Rescan, _requestInfo, 1, CancellationToken.None);

                await checkScanTimesAsync(_requestInfo, 1);
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                ctrlProtocolBox1.ProcessMessage("");
                Program.mainForm.EnableAllTabPages();
                buttonQueryData.Enabled = isScanEnabled && isColumnCheck; ;
                buttonScanTableColumns.Enabled = true;
                Cursor = Cursors.Default;
                if (CM != null) LogMethodEnd(CM);
            }

        }

        private async void buttonRemoveScan_Click(object sender, EventArgs e)
        {
            MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
            try
            {
                Cursor = Cursors.WaitCursor;

                ctrlProtocolBox1.ClearMessages();
                buttonQueryData.Enabled = false;
                buttonScanTableColumns.Enabled = false;
                buttonRemoveScan.Enabled = false;

                Program.mainForm.DisableAllTabPages(this);

                Program.Collector.CleanupUiMessageHandler();
                Program.Collector.ProcessUiMessage += ctrlProtocolBox1.ProcessMessage;

                var _requestInfo = new cF4sdWebRequestInfo("buttonRemoveScan_Click", null);
                await Program.Collector.RemoveLastScanHistoryEntry("NxqlScan-all", _requestInfo, 1, CancellationToken.None);

                await checkScanTimesAsync(_requestInfo, 1);
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                ctrlProtocolBox1.ProcessMessage("");
                Program.mainForm.EnableAllTabPages();
                buttonScanTableColumns.Enabled = true;
                Cursor = Cursors.Default;
                if (CM != null) LogMethodEnd(CM);
            }
        }

        private async void buttonTest_Click(object sender, EventArgs e)
        {
            var ColVaidation = new cNxqlColumnsValidationResult();
            await ColVaidation.LoadFromSqlAsync(Program.Collector, CancellationToken.None, null,0);

            var NxqlCollector = new cNxqlDailyCollector(Program.Collector, ColVaidation);
            if (!Program.Collector.ClusterConfig.Tables.TryGetValue("nxt-device-apps-outlook", out var _tbl))
                return;

            NxqlCollector.CreateJobs(new List<cDataHistoryConfigTable>(1) { _tbl }, DateTime.UtcNow.AddDays(-7), DateTime.UtcNow, "NEXThink", 11261, C4IT.FASD.Base.enumFasdInformationClass.Computer);

            await NxqlCollector.Orchestrator.ProcessAsync(CancellationToken.None);


        }
    }
}
