using System.Runtime.InteropServices;

namespace Hawkeye.VisionBuilder.Features.ToolEditor
{
    public class CodeCompletionControl : ListBox
    {
        private TextBox textBox;
        private readonly Form _form;

        [DllImport("user32.dll")]
        static extern bool GetCaretPos(out Point lpPoint);

        public CodeCompletionControl(TextBox textBox)
        {
            this.textBox = textBox;

            this.Visible = false;
            this.Location = new Point(0, 0);
            this.Width = 200;
            _form = new Form();
            _form.Width = this.Width;
            _form.Height = 200;

            _form.Controls.Add(this);
            this.Dock = DockStyle.Fill;
            _form.FormBorderStyle = FormBorderStyle.None;
            _form.ShowInTaskbar = false;
            _form.TopMost = true;
            _form.StartPosition = FormStartPosition.Manual;
            
            textBox.TextChanged += TextBox_TextChanged;
            textBox.KeyDown += TextBox_KeyDown;

            this.KeyDown += CodeCompletionControl_KeyDown;
        }

        private void CodeCompletionControl_KeyDown(object? sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Up)
            {
                if (this.SelectedIndex == 0)
                {
                    textBox.Focus();
                }
            }
           
            else if (e.KeyCode == Keys.Enter && this.Visible && this.SelectedIndex != -1)
            {
                Accept();
            }else if (e.KeyCode == Keys.Escape)
            {
                this.Visible = false;
                _form.Hide();
            }
        }

        private void Cancel()
        {
            this.Visible = false;
            _form.Hide();
        }

        private void Accept()
        {
            var start = textBox.Text.LastIndexOf(".");
            if (start == -1)
            {
                textBox.Text = this.SelectedItem.ToString();
                textBox.SelectionStart = textBox.Text.Length;
                this.Visible = false;
                _form.Hide();
                return;
            }
            textBox.Text = textBox.Text.Substring(0,start+1);
            textBox.Text += this.SelectedItem.ToString();
            textBox.SelectionStart = textBox.Text.Length;
            this.Visible = false;
            _form.Hide();
        }

        private void TextBox_TextChanged(object sender, EventArgs e)
        {
            if(int.TryParse(textBox.Text,out _))return;
            if (GetCaretPos(out Point point))
            {
                // Convert screen position to client position

                
                // Set location of this control
                _form.Location = textBox.PointToScreen(new Point(point.X, point.Y + textBox.Size.Height)); ; // Add offset to avoid overlap with text cursor
            }

            // Update suggestions
            var suggestions = GetSuggestions(textBox.Text);
            this.Items.Clear();
            this.Items.AddRange(suggestions.ToArray());
            if (this.Items.Count > 0)
            {
                _form.Show();
                textBox.Focus();
            }
            else
            {
                _form.Hide();
            }
            this.Visible = this.Items.Count > 0;
            
        }



        private void TextBox_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Down && this.Visible)
            {
                this.Focus();
                this.SelectedIndex = 0;
            }
            else if (e.KeyCode == Keys.Escape)
            {
                Cancel();
            }
            else if (e.KeyCode == Keys.Enter && this.Visible && this.SelectedIndex != -1)
            {
                Accept();
            }
        }

        public delegate void NeedSugestionsDelegate(string input, List<string> suggestions);
        public event NeedSugestionsDelegate NeedSugestions =delegate{ };

        private List<string> GetSuggestions(string input)
        {
            var source = new List<string>();
            
            NeedSugestions(input, source);
            if (source.Count == 0)
            {
                Visible = false;
                _form.Hide();
            }
            return source.ToList();
        }
    }
}
