using FastReport.Controls;
using FastReport.Utils;
using System.Collections.Generic;
using System.Windows.Forms;
#if !MONO
using FastReport.DevComponents.DotNetBar;
#endif

namespace FastReport.Design.ToolWindows
{
    /// <summary>
    /// Extend the <see cref="ToolWindowBase"/> class for window with TreeView.
    /// </summary>
    public class FilterableToolWindow : ToolWindowBase
    {
        #region Fields
        protected TreeViewMultiSelect tree;
#if !MONO
        protected Bar toolbar;
        protected ButtonItem collapseButton;
        protected ButtonItem expandButton;
#else
        protected ToolStrip toolbar;
        protected ToolStripButton collapseButton;
        protected ToolStripButton expandButton;
#endif
        protected TextBoxButton searchBox;
        protected Splitter splitter;
        #endregion

        #region Private Methods
        private void UpdateSearchBoxImage()
        {
            searchBox.Image = Designer.GetImage(searchBox.Text == "" ? 181 : 51);
        }

        private void TextBox_TextChanged(object sender, System.EventArgs e)
        {
            tree.BeginUpdate();
            UpdateTree();
            UpdateSearchBoxImage();
            
            string text = searchBox.Text;
            if (text != "")
            {
                List<TreeNode> nodes = new List<TreeNode>();
                TreeNode tmpNode;

                foreach (TreeNode node in tree.Nodes)
                {
                    tmpNode = Search(node, text);
                    if (tmpNode != null)
                        nodes.Add(tmpNode);
                }
                tree.Nodes.Clear();

                if (nodes.Count > 0)
                    tree.Nodes.AddRange(nodes.ToArray());
            }
            tree.ExpandAll();
            tree.EndUpdate();

            if(tree.Nodes.Count > 0)
                tree.SelectedNode = tree.Nodes[0];
        }

        private void TextBox_ButtonClick(object sender, System.EventArgs e)
        {
            string text = searchBox.Text;
            if (text != "")
            {
                searchBox.ResetText();
            }
            else
            {
                searchBox.FocusTextBox();
            }
        }

        private void ExpandButton_Click(object sender, System.EventArgs e)
        {
            tree.BeginUpdate();
            tree.ExpandAll();
            tree.SelectedNode = null;
            tree.EndUpdate();
            if (tree.Nodes.Count > 0)
                tree.SelectedNode = tree.Nodes[0];
        }

        private void CollapseButton_Click(object sender, System.EventArgs e)
        {
            tree.CollapseAll();
            if (tree.Nodes.Count == 1)
                tree.Nodes[0].Expand();
        }

        #endregion

        #region Protected Methods
        /// <inheritdoc/>
        protected TreeNode Search(TreeNode treeNode, string search)
        {
            List<TreeNode> nodeCollection = new List<TreeNode>();

            if (treeNode.Nodes.Count > 0)
            {
                TreeNode tmpNode;
                foreach (TreeNode node in treeNode.Nodes)
                {
                    tmpNode = Search(node, search);
                    if (tmpNode != null)
                        nodeCollection.Add(tmpNode);
                }
            }
            treeNode.Nodes.Clear();

            if (nodeCollection.Count > 0)
                treeNode.Nodes.AddRange(nodeCollection.ToArray());

            if (treeNode.Text.ToLower().Contains(search.ToLower()) || treeNode.Nodes.Count > 0)
            {
                return treeNode;
            }
            return null;
        }

        /// <summary>
        /// This method puts data to TreeView.
        /// </summary>
        protected virtual void UpdateTree() { }
        #endregion

        #region Public Methods
        /// <summary>
        /// Initializes a new instance of the <see cref="FilterableToolWindow"/> class with default settings.
        /// </summary>
        /// <param name="designer">The report designer.</param>
        public FilterableToolWindow(Designer designer) : base(designer) 
        {
#if !MONO
            toolbar = new Bar();
            toolbar.Dock = DockStyle.Top;
            toolbar.RoundCorners = false;

            collapseButton = AddButton(184, CollapseButton_Click);
            expandButton = AddButton(183, ExpandButton_Click);
            toolbar.Items.AddRange(new BaseItem[] { collapseButton, expandButton });

            searchBox = new TextBoxButton();
            searchBox.Dock = DockStyle.Top;
            searchBox.ButtonClick += TextBox_ButtonClick;
            searchBox.TextChanged += TextBox_TextChanged;

            tree = new TreeViewMultiSelect();
            tree.Dock = DockStyle.Fill;
            tree.BorderStyle = BorderStyle.None;

            splitter = new Splitter();
            splitter.Dock = DockStyle.Bottom;
            splitter.Visible = true;

            ParentControl.Controls.AddRange( new Control[] { tree, searchBox, splitter, toolbar });

#else
            tree = new TreeViewMultiSelect();
            tree.LabelEdit = true;
            tree.Dock = DockStyle.Fill;
            tree.BorderStyle = BorderStyle.None;

            toolbar = new ToolStrip();
            toolbar.GripStyle = ToolStripGripStyle.Hidden;

            searchBox = new TextBoxButton();
            searchBox.Image = Designer.GetImage(181);
            searchBox.Dock = DockStyle.Top;
            searchBox.Height = 25;
            searchBox.ButtonClick += TextBox_ButtonClick;
            searchBox.TextChanged += TextBox_TextChanged;

            splitter = new Splitter();
            splitter.Dock = DockStyle.Bottom;
            splitter.Visible = true;

            collapseButton = AddButton(184, CollapseButton_Click);
            expandButton = AddButton(183, ExpandButton_Click);
            toolbar.Items.AddRange(new ToolStripItem[] { collapseButton, expandButton });

            Controls.AddRange(new Control[] { tree, splitter, searchBox, toolbar });
#endif
            UpdateDpiDependencies();
        }

        /// <inheritdoc/>
        public override void UpdateUIStyle()
        {
            base.UpdateUIStyle();
#if !MONO
            splitter.BackColor = UIStyleUtils.GetControlColor(Designer.UIStyle);
            toolbar.Style = UIStyleUtils.GetDotNetBarStyle(Designer.UIStyle);
#else
            toolbar.Renderer = UIStyleUtils.GetToolStripRenderer(Designer.UIStyle);
            splitter.BackColor = UIStyleUtils.GetColorTable(Designer.UIStyle).ControlBackColor;
#endif
        }

        /// <inheritdoc/>
        public override void Localize()
        {
#if !MONO
            collapseButton.Tooltip = Res.Get("Designer,ToolWindow,CollapseAll");
            expandButton.Tooltip = Res.Get("Designer,ToolWindow,ExpandAll");
#else
            collapseButton.ToolTipText = Res.Get("Designer,ToolWindow,CollapseAll");
            expandButton.ToolTipText = Res.Get("Designer,ToolWindow,ExpandAll");
#endif
        }

        /// <inheritdoc/>
        public override void UpdateDpiDependencies()
        {
            base.UpdateDpiDependencies();
            tree.ImageList = Designer.GetImages();
            toolbar.Font = Designer.LogicalToDevice(DrawUtils.DefaultFont);
            searchBox.Font = Designer.LogicalToDevice(DrawUtils.DefaultFont);
            searchBox.Height = Designer.LogicalToDevice(22);
            UpdateSearchBoxImage();
#if !MONO
            toolbar.UpdateDpiDependencies();
            UpdateImages(toolbar.Items);
#endif
        }
        #endregion
    }
}