using System;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;
using FastReport.Utils;

namespace FastReport.Controls
{
    /// <summary>
    /// Represents a combobox that allows to choose a color.
    /// </summary>
    /// <remarks>
    /// This control may be useful if you write own components for FastReport.
    /// </remarks>
    [ToolboxItem(false)]
    public class ColorComboBox : UserControl
    {
        private Button comboButton;
        private ColorDropDown dropDown;
        private bool showColorName;
        private Timer timer;
        private int closedTicks;
        private int dpi;

        /// <summary>
        /// This event is raised when you select a color.
        /// </summary>
        public event EventHandler ColorSelected;

        /// <summary>
        /// Gets or sets the selected color.
        /// </summary>
        public Color Color
        {
            get { return dropDown.Color; }
            set
            {
                dropDown.Color = value;
                Refresh();
            }
        }

        /// <summary>
        /// Gets or sets value indicating whether it is necessary to show a color name in a combobox.
        /// </summary>
        [DefaultValue(false)]
        [Category("Appearance")]
        public bool ShowColorName
        {
            get { return showColorName; }
            set
            {
                showColorName = value;
                Refresh();
            }
        }

        private void FComboButton_Click(object sender, EventArgs e)
        {
            if (Math.Abs(Environment.TickCount - closedTicks) < 100)
                return;

            dropDown.Owner = this;
            dropDown.Show(this, new Point(RightToLeft == RightToLeft.Yes ? Width : 0, Height));
        }

        private void FDropDown_ColorSelected(object sender, EventArgs e)
        {
            timer.Start();
            Refresh();
            if (ColorSelected != null)
                ColorSelected(this, EventArgs.Empty);
        }

        private void FDropDown_Closed(object sender, ToolStripDropDownClosedEventArgs e)
        {
            closedTicks = Environment.TickCount;
        }

        private void FTimer_Tick(object sender, EventArgs e)
        {
            FindForm().BringToFront();
            timer.Stop();
        }

        private void LayoutControls()
        {
            if (comboButton != null)
                comboButton.SetBounds(RightToLeft == RightToLeft.Yes ? 1 : Width - Height + 1, 1, Height - 2, Height - 2);
        }

        /// <inheritdoc/>
        protected override void OnPaint(PaintEventArgs e)
        {
            if (dpi != this.Dpi())
            {
                UpdateImages();
                dpi = this.Dpi();
            }

            Graphics g = e.Graphics;
            g.FillRectangle(Enabled ? SystemBrushes.Window : SystemBrushes.Control, DisplayRectangle);
            if (Enabled)
                ControlPaint.DrawVisualStyleBorder(g, new Rectangle(0, 0, Width - 1, Height - 1));
            else
                g.DrawRectangle(SystemPens.InactiveBorder, new Rectangle(0, 0, Width - 1, Height - 1));

            using (Brush b = new SolidBrush(Color))
            {
                int xy = this.LogicalToDevice(4);
                Rectangle rect = new Rectangle(xy, xy, this.LogicalToDevice(24), Height - 2*xy);
                if (RightToLeft == RightToLeft.Yes)
                    rect.X = Width - rect.Left - rect.Width;
                if (Enabled)
                    g.FillRectangle(b, rect);
                g.DrawRectangle(SystemPens.ControlDark, rect);

                if (ShowColorName)
                {
                    string colorName = Converter.ToString(Color);
                    TextFormatFlags flags = TextFormatFlags.VerticalCenter;
                    if (RightToLeft == RightToLeft.Yes)
                    {
                        rect = new Rectangle(0, 0, rect.X - 8, Height);
                        flags |= TextFormatFlags.RightToLeft | TextFormatFlags.Right;
                    }
                    else
                    {
                        rect.X = rect.Right + 8;
                        rect = new Rectangle(rect.X, 0, Width - rect.X, Height);
                    }
                    TextRenderer.DrawText(g, colorName, Font, rect, SystemColors.ControlText, flags);
                }
            }
        }

        private void UpdateImages()
        {
            comboButton.Image = this.GetImage(182);
        }

        /// <inheritdoc/>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (timer != null)
                    timer.Dispose();
                timer = null;
            }
            base.Dispose(disposing);
        }

        /// <inheritdoc/>
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            LayoutControls();
        }

        /// <inheritdoc/>
        protected override void OnLayout(LayoutEventArgs e)
        {
            base.OnLayout(e);
            LayoutControls();
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="ColorComboBox"/> class with default settings.
        /// </summary>
        public ColorComboBox()
        {
            comboButton = new Button();
            comboButton.FlatStyle = FlatStyle.Flat;
            comboButton.FlatAppearance.BorderSize = 0;
            comboButton.Click += FComboButton_Click;
            Controls.Add(comboButton);

            dropDown = new ColorDropDown();
            dropDown.ColorSelected += FDropDown_ColorSelected;
            dropDown.Closed += FDropDown_Closed;

            timer = new Timer();
            timer.Interval = 50;
            timer.Tick += new EventHandler(FTimer_Tick);

            // prevent autoscale of child controls
            AutoScaleMode = AutoScaleMode.None;
            SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);
        }
    }
}
