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 C4IT.Logging;
using C4IT.XML;
using C4IT.DataHistoryProvider;
using C4IT.FASD.Base;

using static C4IT.Logging.cLogManager;
using Newtonsoft.Json.Linq;
using static C4IT.DataHistoryProvider.cNxqlDailyCollector;

namespace C4IT_DataHistoryProvider_Test
{
    public partial class ctrlTestFunctions : UserControl
    {
        private readonly List<string> MessageLines = new List<string>();

        public ctrlTestFunctions()
        {
            InitializeComponent();
        }

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

            if (Program.Collector == null)
                return;

            try
            {
                Cursor = Cursors.WaitCursor;

                ctrlProtocolBox1.ClearMessages();

                Program.mainForm.DisableAllTabPages(this);

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

                var _requestInfo = new cF4sdWebRequestInfo("ctrlTestFunctions_Load", null);
                await GetUsersAndComputersAsync(_requestInfo, 1);

                if (Program.Collector.M42WpmCollector != null)
                    await Program.Collector.M42WpmCollector.ValidateConnectionAsync(true, CancellationToken.None);

                if (Program.Collector.CitrixCollector != null)
                    await Program.Collector.CitrixCollector.ValidateConnectionsAsync(CancellationToken.None);

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

        private async Task GetUsersAndComputersAsync(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
            {
                Program.UserList = await Program.Collector.GetInfoClassListTest(C4IT.FASD.Base.enumFasdInformationClass.User, checkBoxFiltered.Checked, requestInfo, LogDeep+1, CancellationToken.None);

                comboBoxUserSelect.Items.AddRange(Program.UserList.ToArray());
                ctrlProtocolBox1.ProcessMessage("");

                var list = await Program.Collector.GetInfoClassListTest(C4IT.FASD.Base.enumFasdInformationClass.Computer, checkBoxFiltered.Checked, requestInfo, LogDeep+1, CancellationToken.None); ; ;
                comboBoxComputerSelect.Items.AddRange(list.ToArray());
                ctrlProtocolBox1.ProcessMessage("");
            }
            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);
            }

        }

        public void ProcessMessage(cDataHistoryUiStatusMessage Message)
        {
            string line = new string(' ', Message.Indent * 3) + Message.Message;
            ctrlProtocolBox1.ProcessMessage(line);
        }

        private async void buttonGetUserComputerActivities_Click(object sender, EventArgs e)
        {
            MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
            try
            {
                if (!(comboBoxUserSelect.SelectedItem is cDataHistoryInfoClassListEntry Entry))
                    return;

                var RetVal = await Program.Collector.GetUsageFromAgentData(C4IT.FASD.Base.enumFasdInformationClass.User, new List<Guid>() { Entry.id }, 90, CancellationToken.None, null, 0);
                ctrlProtocolBox1.ProcessMessage("");
                if (RetVal == null || RetVal.Count == 0)
                    ctrlProtocolBox1.ProcessMessage("no further information found.");
                else
                {
                    ctrlProtocolBox1.ProcessMessage($"{RetVal.Count} related objects found:");

                    // fill the drop down boxes for the realtions found
                    comboBoxTickets.Items.Clear();
                    comboBoxSessions.Items.Clear();
                    foreach (var Entry2 in RetVal)
                    {
                        switch(Entry2.Type)
                        {
                            case enumF4sdSearchResultClass.Ticket:
                                comboBoxTickets.Items.Add(Entry2);
                                break;
                            case enumF4sdSearchResultClass.VirtualSession:
                                if (!string.IsNullOrEmpty(Entry2.DisplayName))
                                    comboBoxSessions.Items.Add(Entry2);
                                break;
                        }

                        ctrlProtocolBox1.ProcessMessage($"  {Entry2.Type} {Entry2.Name} {{{Entry2.id}}}:");
                        ctrlProtocolBox1.ProcessMessage($"    LastUsed: {Entry2.LastUsed}");
                        ctrlProtocolBox1.ProcessMessage($"    Usage weight: {Entry2.UsingLevel}");
                        foreach (var Entry3 in Entry2.Infos)
                            ctrlProtocolBox1.ProcessMessage($"    {Entry3.Key}: {Entry3.Value}");
                    }

                    if (comboBoxTickets.Items.Count > 0)
                        comboBoxTickets.SelectedIndex = 0;
                    if (comboBoxSessions.Items.Count > 0)
                        comboBoxSessions.SelectedIndex = 0;


                }
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                if (CM != null) LogMethodEnd(CM);
            }
        }

        private async void buttonComputerUserActivities_Click(object sender, EventArgs e)
        {
            MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
            try
            {
                if (!(comboBoxComputerSelect.SelectedItem is cDataHistoryInfoClassListEntry Entry))
                    return;

                var RetVal = await Program.Collector.GetUsageFromAgentData(C4IT.FASD.Base.enumFasdInformationClass.Computer, new List<Guid>() { Entry.id }, 90, CancellationToken.None, null, 0);
                ctrlProtocolBox1.ProcessMessage("");
                if (RetVal == null || RetVal.Count == 0)
                    ctrlProtocolBox1.ProcessMessage("no users found.");
                else
                {
                    ctrlProtocolBox1.ProcessMessage($"{RetVal.Count} related users found:");
                    foreach (var Entry2 in RetVal)
                    {
                        ctrlProtocolBox1.ProcessMessage($"  {Entry2.Type} {Entry2.Name} {{{Entry2.id}}}:");
                        ctrlProtocolBox1.ProcessMessage($"    LastUsed: {Entry2.LastUsed}");
                        ctrlProtocolBox1.ProcessMessage($"    Usage weight: {Entry2.UsingLevel}");
                        foreach (var Entry3 in Entry2.Infos)
                            ctrlProtocolBox1.ProcessMessage($"    {Entry3.Key}: {Entry3.Value}");
                    }
                }
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                if (CM != null) LogMethodEnd(CM);
            }
        }

        private void comboBoxUserSelect_SelectedValueChanged(object sender, EventArgs e)
        {
            comboBoxTickets.Items.Clear();
            comboBoxTickets.SelectedItem = null;

            GetTables();
        }

        private void comboBoxComputerSelect_SelectedValueChanged(object sender, EventArgs e)
        {
            GetTables();
        }

        private void comboBoxTickets_SelectedValueChanged(object sender, EventArgs e)
        {
            GetTables();
        }

        private void comboBoxSessions_SelectedValueChanged(object sender, EventArgs e)
        {
            GetTables();
        }

        private void GetTables()
        {
            MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
            try
            {
                bool HasUser = comboBoxUserSelect.SelectedItem != null;
                bool HasComputer = comboBoxComputerSelect.SelectedItem != null;
                bool HasTicket = comboBoxTickets.SelectedItem != null;
                bool HasSession = comboBoxSessions.SelectedItem != null;

                var Tables = new List<cDataHistoryConfigTable>();
                foreach (var table in Program.Collector.ClusterConfig.Tables.Values)
                {
                    if ((HasUser && table.ParentCluster.InformationClass == C4IT.FASD.Base.enumFasdInformationClass.User) ||
                        (HasComputer && table.ParentCluster.InformationClass == C4IT.FASD.Base.enumFasdInformationClass.Computer) ||
                        (HasTicket && table.ParentCluster.InformationClass == C4IT.FASD.Base.enumFasdInformationClass.Ticket) ||
                        (HasSession && table.ParentCluster.InformationClass == enumFasdInformationClass.VirtualSession))
                    {
                        Tables.Add(table);
                    }
                }

                comboBoxTable.Items.Clear();
                if (Tables.Count == 0)
                {
                    comboBoxTable.Enabled = false;
                }
                else
                {
                    comboBoxTable.Items.AddRange(Tables.ToArray());
                    comboBoxTable.Enabled = true;
                }
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                if (CM != null) LogMethodEnd(CM);
            }
        }

        private void comboBoxTable_SelectedValueChanged(object sender, EventArgs e)
        {
            buttonGetRawValues.Enabled = comboBoxTable.SelectedItem != null;
        }

        private void ListSelectionRecords(cF4SDHealthCardRawData.cHealthCardTable _tableResult, int Offset)
        {
            var _cnt = _tableResult.Columns.First().Value.Values.Count;
            for (int i = 0; i < _cnt; i++)
            {
                {
                    var strLine = $"";
                    foreach (var _col in _tableResult.Columns.Values)
                    {
                        if (strLine != "")
                            strLine += " | ";
                        else
                            strLine = $"{i + Offset} : ";
                        strLine += _col.Values[i]?.ToString();
                    }
                    ctrlProtocolBox1.ProcessMessage($"     " + strLine);
                }
            }
        }

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

                var Identities = new List<cF4sdIdentityEntry>();
                if (comboBoxComputerSelect.SelectedItem is cDataHistoryInfoClassListEntry ComputerEntry)
                    Identities.Add(new cF4sdIdentityEntry() { Class = enumFasdInformationClass.Computer, Id = ComputerEntry.id });
                if (comboBoxUserSelect.SelectedItem is cDataHistoryInfoClassListEntry UserEntry)
                    Identities.Add(new cF4sdIdentityEntry() { Class = enumFasdInformationClass.User, Id = UserEntry.id, AccountType = enumAccountType.AD });
                if (comboBoxTickets.SelectedItem is cF4sdApiSearchResultRelation TicketEntry)
                    Identities.Add(new cF4sdIdentityEntry() { Class = enumFasdInformationClass.Ticket, Id = TicketEntry.id });
                if (comboBoxSessions.SelectedItem is cF4sdApiSearchResultRelation SessionEntry)
                    Identities.Add(new cF4sdIdentityEntry() { Class = enumFasdInformationClass.VirtualSession, Id = SessionEntry.id, Instance = SessionEntry.Instance });
                if (!(comboBoxTable.SelectedItem is cDataHistoryConfigTable Table))
                    return;

                if (Identities.Count == 0 || comboBoxTable.SelectedItem == null)
                    return;

                ctrlProtocolBox1.ProcessMessage("");

                if (Table.Type == eDataHistoryTableType.Events || Table.Type == eDataHistoryTableType.StaticDetails)
                {
                    var Res = await Program.Collector.GetDetailsTableResultsAsync(new List<string>() { Table.Name }, Identities, DateTime.Now.Date.ToUniversalTime(), 90, CancellationToken.None, null,0);

                    if (Res == null || Res.Count == 0)
                    {
                        ctrlProtocolBox1.ProcessMessage("could not get a valid raw table");
                        return;
                    }

                    foreach (var _Table in Res)
                    {
                        ctrlProtocolBox1.ProcessMessage("");
                        ctrlProtocolBox1.ProcessMessage($"resulting table name: {_Table.Name}");
                        ctrlProtocolBox1.ProcessMessage("  the table is an event details table");

                        ctrlProtocolBox1.ProcessMessage("");
                        var strCols = "";
                        foreach (var strCol in _Table.Columns)
                        {
                            if (strCols != "")
                                strCols += " | ";
                            strCols += strCol;
                        }
                        ctrlProtocolBox1.ProcessMessage("  Event columns: " + strCols);

                        foreach (var _day in _Table.Values)
                        {
                            ctrlProtocolBox1.ProcessMessage($"     Day {_day.Key}:");
                            foreach (var _event in _day.Value)
                            {
                                var strLine = "";
                                foreach (var val in _event)
                                {
                                    if (strLine != "")
                                        strLine += " | ";
                                    strLine += (val != null) ? val.ToString() : null;
                                }
                                ctrlProtocolBox1.ProcessMessage($"     " + strLine);
                            }
                        }
                    }
                }
                else if (Table.Type == eDataHistoryTableType.Selection)
                {
                    var _Count = await Program.Collector.GetSelectionTableResultCountAsync(Table.Name, Identities, null, null, CancellationToken.None);
                    if (_Count > 0)
                    {
                        var _tableResult = await Program.Collector.GetSelectionTableResultAsync(Table.Name, Identities, "", 15, 0, null, CancellationToken.None);
                        if (_tableResult != null)
                        {
                            ctrlProtocolBox1.ProcessMessage("");
                            ctrlProtocolBox1.ProcessMessage($"resulting table name: {_tableResult.Name}");
                            ctrlProtocolBox1.ProcessMessage($"  the table is a selection table, {_Count} entries determined.");

                            ctrlProtocolBox1.ProcessMessage("");
                            var strCols = "";
                            foreach (var strCol in _tableResult.Columns.Keys)
                            {
                                if (strCols != "")
                                    strCols += " | ";
                                strCols += strCol;
                            }
                            ctrlProtocolBox1.ProcessMessage("  Columns: " + strCols);

                            ListSelectionRecords(_tableResult, 0);

                            if (_Count > 15)
                            {
                                _tableResult = await Program.Collector.GetSelectionTableResultAsync(Table.Name, Identities, "", 15, 1, null, CancellationToken.None);
                                ctrlProtocolBox1.ProcessMessage("");
                                ListSelectionRecords(_tableResult, 15);

                            }
                        }
                    }
                }
                else
                {
                    var Res = await Program.Collector.GetTableResults(new List<string>() { Table.Name }, Identities, DateTime.Now.Date.ToUniversalTime(), 14, true, CancellationToken.None, null,0);

                    if (Res == null || Res.Tables.Count == 0)
                    {
                        ctrlProtocolBox1.ProcessMessage("could not get a valid raw table");
                        return;
                    }

                    foreach (var _Table in Res.Tables.Values)
                    {
                        ctrlProtocolBox1.ProcessMessage("");
                        ctrlProtocolBox1.ProcessMessage($"resulting table name: {_Table.Name}");
                        switch (_Table.TableType)
                        {
                            case eDataHistoryTableType.Static:
                                ctrlProtocolBox1.ProcessMessage("  the table is static");
                                break;
                            case eDataHistoryTableType.History:
                                ctrlProtocolBox1.ProcessMessage("  the table is historical");
                                break;
                            case eDataHistoryTableType.HistoryEvents:
                                ctrlProtocolBox1.ProcessMessage("  the table is a historical event table");
                                break;
                        }

                        ctrlProtocolBox1.ProcessMessage("");
                        ctrlProtocolBox1.ProcessMessage("Values:");
                        foreach (var Entry in _Table.Columns.Values)
                        {
                            if (Entry.ColumnName == "Printers")
                            {
                            }
                            ctrlProtocolBox1.ProcessMessage($"  [{Entry.ColumnName}]: {getValueString(Entry.Values)}");
                        }
                    }

                }

            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                Cursor = Cursors.Default;
                this.Enabled = true;
                if (CM != null) LogMethodEnd(CM);
            }


        }

        private string getValueString(List<object> Values)
        {
            var RetVal = "";
            if (Values != null && Values.Count > 0)
                foreach (var Entry in Values)
                {
                    if (RetVal != "")
                        RetVal += " | ";
                    var val = Entry?.ToString();
                    if (val != null && val.Length > 200)
                        val = val.Substring(0, 197) + "...";
                    RetVal += (Entry == null) ? "-" : val;
                }

            return RetVal;
        }

        private void buttonClear_Click(object sender, EventArgs e)
        {
            MessageLines.Clear();
            ctrlProtocolBox1.ClearMessages();
        }

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

                var _requestInfo = new cF4sdWebRequestInfo("checkBoxFiltered_CheckedChanged", null);
                await GetUsersAndComputersAsync(_requestInfo, 1);

            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                Cursor = Cursors.Default;
                this.Enabled = true;
                if (CM != null) LogMethodEnd(CM);
            }


        }

    }
}
