using System.Linq;
using Terminal.Gui;

namespace UICatalog.Scenarios;

[ScenarioMetadata ("Interactive Tree", "Create nodes and child nodes in TreeView.")]
[ScenarioCategory ("Controls")]
[ScenarioCategory ("TreeView")]
public class InteractiveTree : Scenario
{
    private TreeView _treeView;

    public override void Setup ()
    {
        Win.Title = GetName ();
        Win.Y = 1; // menu
        Win.Height = Dim.Fill (1); // status bar

        var menu = new MenuBar
        {
            Menus =
            [
                new MenuBarItem ("_File", new MenuItem [] { new ("_Quit", "", Quit) })
            ]
        };
        Application.Top.Add (menu);

        _treeView = new TreeView { X = 0, Y = 0, Width = Dim.Fill (), Height = Dim.Fill (1) };
        _treeView.KeyDown += TreeView_KeyPress;

        Win.Add (_treeView);

        var statusBar = new StatusBar (
                                       new StatusItem []
                                       {
                                           new (
                                                Application.QuitKey,
                                                $"{Application.QuitKey} to Quit",
                                                Quit
                                               ),
                                           new (
                                                KeyCode.CtrlMask | KeyCode.C,
                                                "~^C~ Add Child",
                                                AddChildNode
                                               ),
                                           new (
                                                KeyCode.CtrlMask | KeyCode.T,
                                                "~^T~ Add Root",
                                                AddRootNode
                                               ),
                                           new (
                                                KeyCode.CtrlMask | KeyCode.R,
                                                "~^R~ Rename Node",
                                                RenameNode
                                               )
                                       }
                                      );
        Application.Top.Add (statusBar);
    }

    private void AddChildNode ()
    {
        ITreeNode node = _treeView.SelectedObject;

        if (node != null)
        {
            if (GetText ("Text", "Enter text for node:", "", out string entered))
            {
                node.Children.Add (new TreeNode (entered));
                _treeView.RefreshObject (node);
            }
        }
    }

    private void AddRootNode ()
    {
        if (GetText ("Text", "Enter text for node:", "", out string entered))
        {
            _treeView.AddObject (new TreeNode (entered));
        }
    }

    private bool GetText (string title, string label, string initialText, out string enteredText)
    {
        var okPressed = false;

        var ok = new Button { Text = "Ok", IsDefault = true };

        ok.Accept += (s, e) =>
                      {
                          okPressed = true;
                          Application.RequestStop ();
                      };
        var cancel = new Button { Text = "Cancel" };
        cancel.Accept += (s, e) => Application.RequestStop ();
        var d = new Dialog { Title = title, Buttons = [ok, cancel] };

        var lbl = new Label { X = 0, Y = 1, Text = label };

        var tf = new TextField { Text = initialText, X = 0, Y = 2, Width = Dim.Fill () };

        d.Add (lbl, tf);
        tf.SetFocus ();

        Application.Run (d);

        enteredText = okPressed ? tf.Text : null;

        return okPressed;
    }

    private void Quit () { Application.RequestStop (); }

    private void RenameNode ()
    {
        ITreeNode node = _treeView.SelectedObject;

        if (node != null)
        {
            if (GetText ("Text", "Enter text for node:", node.Text, out string entered))
            {
                node.Text = entered;
                _treeView.RefreshObject (node);
            }
        }
    }

    private void TreeView_KeyPress (object sender, Key obj)
    {
        if (obj.KeyCode == KeyCode.Delete)
        {
            ITreeNode toDelete = _treeView.SelectedObject;

            if (toDelete == null)
            {
                return;
            }

            obj.Handled = true;

            // if it is a root object remove it
            if (_treeView.Objects.Contains (toDelete))
            {
                _treeView.Remove (toDelete);
            }
            else
            {
                ITreeNode parent = _treeView.GetParent (toDelete);

                if (parent == null)
                {
                    MessageBox.ErrorQuery (
                                           "Could not delete",
                                           $"Parent of '{toDelete}' was unexpectedly null",
                                           "Ok"
                                          );
                }
                else
                {
                    //update the model
                    parent.Children.Remove (toDelete);

                    //refresh the tree
                    _treeView.RefreshObject (parent);
                }
            }
        }
    }
}
