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 System.IO;
using System.Diagnostics;

using Newtonsoft.Json;

using C4IT.Logging;
using C4IT.LIAM;
using System.Reflection;
using static C4IT.Logging.cLogManager;

namespace LiamTestTeams
{
    public partial class ctrlTabLiam : UserControl
    {

        public ctrlTabLiam()
        {
            InitializeComponent();
        }

        public void SetTitle(string Title)
        {
            labelTitel.Text = Title;
        }

        public async Task Refresh(TreeNodeRoot RootNode)
        {
            treeViewTeams.Nodes.Clear();


            var listGroups = await RootNode.ResolveAsync();
            ShowErrorMessage(RootNode.getLastError());

            if (listGroups == null)
                return;

            foreach (var Entry in listGroups)
            {
                var tr = new TreeNode(Entry.ToString())
                {
                    ImageIndex = Entry.ImageIndex(),
                    SelectedImageIndex = Entry.ImageIndex(),
                    Tag = Entry,
                    ForeColor = Color.Gray,
                };
                treeViewTeams.Nodes.Add(tr);
            }
        }

        private async void treeViewTeams_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if (treeViewTeams.SelectedNode == null && treeViewTeams.SelectedNode.Tag == null)
            {
                textBoxDetails.Text = "";
                return;
            }

            var tag = treeViewTeams.SelectedNode.Tag;

            if (tag is TreeNodeBase NodeInfo)
            {
                if (NodeInfo.SupportPermissionAdd())
                    toolStripMenuItemAddPermission.Enabled = true;
                else
                    toolStripMenuItemAddPermission.Enabled = false;
                if (NodeInfo.SupportPermissionRemoveDirect() || NodeInfo.SupportPermissionRemoveByValue())
                    toolStripMenuItemRemovePermission.Enabled = true;
                else
                    toolStripMenuItemRemovePermission.Enabled = false;
                if (NodeInfo.GetUID() != null)
                    toolStripMenuItemLoadFromUID.Enabled = true;
                else
                    toolStripMenuItemLoadFromUID.Enabled = false;

                if (NodeInfo.IsResolved())
                {
                    textBoxDetails.Text = NodeInfo.GetInfoText();
                    return;
                }

                Cursor = Cursors.WaitCursor;
                treeViewTeams.Enabled = false;
                try
                {
                    await UpdateNode(treeViewTeams.SelectedNode, false);
                }
                catch { };

                treeViewTeams.Enabled = true;
                Cursor = Cursors.Default;
            }

        }

        private async Task UpdateNode(TreeNode Node, bool ResolveAlways)
        {
            try
            {
                Node.Nodes.Clear();

                if (!(Node.Tag is TreeNodeBase NodeInfo))
                {
                    Node.Text = "- Error -";
                    Node.ImageIndex = 7;
                    Node.SelectedImageIndex = 7;
                    return;
                }

                var SubItems = await NodeInfo.ResolveAsync(ResolveAlways);
                ShowErrorMessage(NodeInfo.getLastError());

                textBoxDetails.Text = NodeInfo.GetInfoText();

                if (SubItems != null)
                {
                    Node.ImageIndex = NodeInfo.ImageIndex();
                    Node.SelectedImageIndex = Node.ImageIndex;
                    treeViewTeams.BeginUpdate();
                    try
                    {
                        foreach (var Entry in SubItems)
                        {
                            var tr = new TreeNode(Entry.ToString())
                            {
                                Tag = Entry,
                                ImageIndex = Entry.ImageIndex(),
                                SelectedImageIndex = Entry.ImageIndex()
                            };

                            if (Entry.AutoResolved())
                                tr.ForeColor = Color.Black;
                            else
                                tr.ForeColor = Color.Gray;

                            treeViewTeams.SelectedNode.Nodes.Add(tr);
                        }
                        treeViewTeams.SelectedNode.Expand();
                        treeViewTeams.SelectedNode.ForeColor = Color.Black;
                    }
                    catch (Exception E)
                    {
                        cLogManager.LogException(E);
                    }
                    finally
                    {
                        treeViewTeams.EndUpdate();
                    }
                }
                else
                {
                    Node.ImageIndex = 7;
                    Node.SelectedImageIndex = 7;
                }
            }
            catch (Exception E)
            {
                cLogManager.LogException(E);
                Node.ImageIndex = 7;
                Node.SelectedImageIndex = 7;
            }
        }

        private void toolStripMenuItemGetJson_Click(object sender, EventArgs e)
        {

            try
            {
                if (treeViewTeams.SelectedNode == null)
                    return;

                if (!(treeViewTeams.SelectedNode.Tag is TreeNodeBase tn))
                    return;

                var strJson = tn.GetJson();

                if (string.IsNullOrWhiteSpace(strJson))
                    return;

                var FN = Path.GetTempPath();
                FN = Path.Combine(FN, "LiamTestTeams");
                Directory.CreateDirectory(FN);
                var FN2 = cLogManagerFile.BuildFileName(treeViewTeams.SelectedNode.Text) + ".json";
                FN = Path.Combine(FN, FN2);

                File.WriteAllText(FN, strJson);

                var strEditor = Environment.ExpandEnvironmentVariables(@"%ProgramFiles%\Notepad++\notepad++.exe");
                if (!File.Exists(strEditor))
                    strEditor = Environment.ExpandEnvironmentVariables(@"%ProgramFiles(x86)%\Notepad++\notepad++.exe");
                if (!File.Exists(strEditor))
                    strEditor = Environment.ExpandEnvironmentVariables(@"%windir%\notepad.exe");

                var PI = new ProcessStartInfo()
                {
                    FileName = strEditor,
                    Arguments = "\"" + FN + "\"",
                    UseShellExecute = false
                };

                Process.Start(PI);

            }
            catch (Exception E)
            {
                cLogManager.LogException(E);
            }

        }

        private async void ToolStripMenuItemRefresh_Click(object sender, EventArgs e)
        {
            try
            {
                if (treeViewTeams.SelectedNode == null)
                    return;

                if (!(treeViewTeams.SelectedNode.Tag is TreeNodeBase tn))
                    return;

                Cursor = Cursors.WaitCursor;
                treeViewTeams.Enabled = false;
                   
                await UpdateNode(treeViewTeams.SelectedNode, true);
            }
            catch (Exception E)
            {
                cLogManager.LogException(E);
            }
            finally
            {
                treeViewTeams.Enabled = true;
                Cursor = Cursors.Default;
            }
        }

        private async void toolStripMenuItemAddPermission_Click(object sender, EventArgs e)
        {
            try
            {
                if (treeViewTeams.SelectedNode == null)
                    return;

                if (!(treeViewTeams.SelectedNode.Tag is TreeNodeBase tn))
                    return;

                if (!tn.SupportPermissionAdd())
                    return;

                var ValidRoles = tn.ValidPermissionRoles();
                if (ValidRoles == null || ValidRoles.Count == 0)
                    return;

                var dlgInput = new frmPermissionInput();

                dlgInput.comboBoxRole.Items.Clear();
                foreach (var Entry in ValidRoles)
                    dlgInput.comboBoxRole.Items.Add(Entry);

                var Retval = dlgInput.ShowDialog();
                if (Retval != DialogResult.OK)
                    return;

                var User = dlgInput.textBoxEmail.Text.Trim();

                eLiamAccessRoles Role;
                switch (dlgInput.comboBoxRole.SelectedIndex)
                {
                    case 0:
                        Role = eLiamAccessRoles.Read;
                        break;
                    case 1:
                        Role = eLiamAccessRoles.Write;
                        break;
                    case 2:
                        Role = eLiamAccessRoles.Owner;
                        break;
                    default:
                        return;
                }

                Cursor = Cursors.WaitCursor;
                treeViewTeams.Enabled = false;

                await tn.AddPermission(Role, User);
                var LastMessage = tn.getLastError();
                await Task.Delay(100);
                await UpdateNode(treeViewTeams.SelectedNode, true);
                if (!string.IsNullOrEmpty(LastMessage))
                    ShowErrorMessage(LastMessage);
            }
            catch (Exception E)
            {
                cLogManager.LogException(E);
            }
            finally
            {
                treeViewTeams.Enabled = true;
                Cursor = Cursors.Default;
            }

        }

        private async void toolStripMenuItemRemovePermission_Click(object sender, EventArgs e)
        {
            try
            {
                if (treeViewTeams.SelectedNode == null)
                    return;

                if (!(treeViewTeams.SelectedNode.Tag is TreeNodeBase tn))
                    return;

                if (tn.SupportPermissionRemoveDirect())
                {
                    Cursor = Cursors.WaitCursor;
                    treeViewTeams.Enabled = false;

                    await tn.RemovePermissionDirect();
                    var LastMessage2 = tn.getLastError();
                    await Task.Delay(100);
                    await UpdateNode(treeViewTeams.SelectedNode.Parent, true);
                    if (!string.IsNullOrEmpty(LastMessage2))
                        ShowErrorMessage(LastMessage2);
                    return;
                }

                if (!tn.SupportPermissionRemoveByValue())
                    return;

                var ValidRoles = tn.ValidPermissionRoles();
                if (ValidRoles == null || ValidRoles.Count == 0)
                    return;

                var dlgInput = new frmPermissionInput();

                dlgInput.comboBoxRole.Items.Clear();
                foreach (var Entry in ValidRoles)
                    dlgInput.comboBoxRole.Items.Add(Entry);

                var Retval = dlgInput.ShowDialog();
                if (Retval != DialogResult.OK)
                    return;

                var User = dlgInput.textBoxEmail.Text.Trim();

                eLiamAccessRoles Role;
                switch (dlgInput.comboBoxRole.SelectedIndex)
                {
                    case 0:
                        Role = eLiamAccessRoles.Read;
                        break;
                    case 1:
                        Role = eLiamAccessRoles.Write;
                        break;
                    default:
                        return;
                }


                Cursor = Cursors.WaitCursor;
                treeViewTeams.Enabled = false;

                await tn.RemovePermissionByValue(Role, User);
                var LastMessage = tn.getLastError();
                await Task.Delay(100);
                await UpdateNode(treeViewTeams.SelectedNode, true);
                if (!string.IsNullOrEmpty(LastMessage))
                    ShowErrorMessage(LastMessage);
                return;
            }
            catch (Exception E)
            {
                cLogManager.LogException(E);
            }
            finally
            {
                treeViewTeams.Enabled = true;
                Cursor = Cursors.Default;
            }

        }

        public void ShowErrorMessage(string Message)
        {
            Invoke(new MethodInvoker(() => {
                if (string.IsNullOrWhiteSpace(Message))
                {
                    textBoxErrorMessage.Text = "";
                    textBoxErrorMessage.Visible = false;
                    textBoxDetails.Height = textBoxErrorMessage.Bottom - textBoxDetails.Top;
                }
                else
                {
                    textBoxErrorMessage.Text = Message;
                    textBoxErrorMessage.Visible = true;
                    textBoxDetails.Height = textBoxErrorMessage.Top - textBoxDetails.Top - 1;
                }
            }));
        }

        private async void toolStripMenuItemLoadFromUID_Click(object sender, EventArgs e)
        {   
            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                if (treeViewTeams.SelectedNode == null)
                    return;

                if (!(treeViewTeams.SelectedNode.Tag is TreeNodeBase tn))
                    return;

                var myUID = tn.GetUID();
                if (myUID != null)
                {
                    var N = await tn.LoadFromUID();
                    if (N != null && N.GetUID() == myUID)
                    {
                        var IT = N.GetInfoText();

                        var childs = await N.ResolveAsync(true);
                        if (childs != null)
                            IT += $"\r\n\r\nchild count: {childs.Count}";
                        else
                            IT += $"\r\n\r\n*** Error resolving child nodes ***";

                        MessageBox.Show(this, IT, $"Result for '{N.ToString()}'", MessageBoxButtons.OK, MessageBoxIcon.Information);
                        return;
                    }
                }

                MessageBox.Show(this, "Error loading node from UID", $"UID = {myUID}", MessageBoxButtons.OK, MessageBoxIcon.Error);

            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                LogMethodEnd(CM);
            }


        }
    }

}
