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

namespace FastReport.Dialog
{
    partial class DialogControl : IHasEditor
    {
        #region Protected Methods
        /// <summary>
        /// Determines whether is necessary to serialize the <b>BackColor</b> property.
        /// </summary>
        /// <returns><b>true</b> if serialization is necessary.</returns>
        protected virtual bool ShouldSerializeBackColor()
        {
            return BackColor != SystemColors.Control;
        }

        /// <summary>
        /// Determines whether is necessary to serialize the <b>Cursor</b> property.
        /// </summary>
        /// <returns><b>true</b> if serialization is necessary.</returns>
        protected virtual bool ShouldSerializeCursor()
        {
            return Cursor != Cursors.Default;
        }

        /// <summary>
        /// Determines whether is necessary to serialize the <b>Font</b> property.
        /// </summary>
        /// <returns><b>true</b> if serialization is necessary.</returns>
        protected virtual bool ShouldSerializeFont()
        {
            return !Font.Equals(Control.Parent.Font);
        }

        /// <summary>
        /// Determines whether is necessary to serialize the <b>ForeColor</b> property.
        /// </summary>
        /// <returns><b>true</b> if serialization is necessary.</returns>
        protected virtual bool ShouldSerializeForeColor()
        {
            return ForeColor != SystemColors.ControlText;
        }

        /// <inheritdoc/>
        protected override SelectionPoint[] GetSelectionPoints()
        {
            return new SelectionPoint[] {
                new SelectionPoint(AbsLeft - 2, AbsTop - 2, SizingPoint.LeftTop),
                new SelectionPoint(AbsLeft + Width + 1, AbsTop - 2, SizingPoint.RightTop),
                new SelectionPoint(AbsLeft - 2, AbsTop + Height + 1, SizingPoint.LeftBottom),
                new SelectionPoint(AbsLeft + Width + 1, AbsTop + Height + 1, SizingPoint.RightBottom),
                new SelectionPoint(AbsLeft + Width / 2, AbsTop - 2, SizingPoint.TopCenter),
                new SelectionPoint(AbsLeft + Width / 2, AbsTop + Height + 1, SizingPoint.BottomCenter),
                new SelectionPoint(AbsLeft - 2, AbsTop + Height / 2, SizingPoint.LeftCenter),
                new SelectionPoint(AbsLeft + Width + 1, AbsTop + Height / 2, SizingPoint.RightCenter) };
        }

        /// <summary>
        /// Draws the selection point.
        /// </summary>
        /// <param name="g"><b>Graphics</b> object to draw on.</param>
        /// <param name="p"><see cref="Pen"/> object.</param>
        /// <param name="b"><see cref="Brush"/> object.</param>
        /// <param name="x">Left coordinate.</param>
        /// <param name="y">Top coordinate.</param>
        protected void DrawSelectionPoint(Graphics g, Pen p, Brush b, float x, float y)
        {
            x = (int)x;
            y = (int)y;
            g.FillRectangle(b, x - 2, y - 2, 5, 5);
            g.DrawLine(p, x - 2, y - 3, x + 2, y - 3);
            g.DrawLine(p, x - 2, y + 3, x + 2, y + 3);
            g.DrawLine(p, x - 3, y - 2, x - 3, y + 2);
            g.DrawLine(p, x + 3, y - 2, x + 3, y + 2);
        }
        #endregion

        #region Public Methods
        /// <inheritdoc/>
        public override void CheckParent(bool immediately)
        {
            if (!IsSelected || IsAncestor || !HasFlag(Flags.CanChangeParent))
                return;

            if (immediately || (!(Parent is DialogPage) && (
              Left < 0 || Left > (Parent as ComponentBase).Width || Top < 0 || Top > (Parent as ComponentBase).Height)))
            {
                ObjectCollection list = Page.AllObjects;
                int i = 0;
                while (i < list.Count)
                {
                    if (list[i] is ParentControl && list[i] != this)
                        i++;
                    else
                        list.RemoveAt(i);
                }
                list.Insert(0, Page);

                for (i = list.Count - 1; i >= 0; i--)
                {
                    ComponentBase c = list[i] as ComponentBase;
                    if ((c as IParent).CanContain(this))
                        if (AbsLeft > c.AbsLeft - 1e-4 && AbsLeft < c.AbsRight - 1e-4 &&
                          AbsTop > c.AbsTop - 1e-4 && AbsTop < c.AbsBottom - 1e-4)
                        {
                            if (Parent != c)
                            {
                                Left = (int)Math.Round((AbsLeft - c.AbsLeft) / Page.SnapSize.Width) * Page.SnapSize.Width;
                                Top = (int)Math.Round((AbsTop - c.AbsTop) / Page.SnapSize.Height) * Page.SnapSize.Height;
                                Parent = c;
                            }
                            break;
                        }
                }
            }
        }

        /// <inheritdoc/>
        public override void DrawSelection(FRPaintEventArgs e)
        {
            float m = Report?.Designer?.DpiMultiplier() ?? 1;
            Pen pen = e.Cache.GetPen(Color.Gray, m, DashStyle.Dot);
            e.Graphics.DrawRectangle(pen, AbsLeft - 2 * m, AbsTop - 2 * m, Width + 3.5f * m, Height + 3.5f * m);
            base.DrawSelection(e);
        }

        /// <summary>
        /// Creates the empty event handler for the <b>ClickEvent</b> event in the report's script.
        /// </summary>
        /// <returns><b>true</b> if event handler was created successfully.</returns>
        public bool InvokeEditor()
        {
            Report.Designer.ActiveReportTab.SwitchToCode();
            if (String.IsNullOrEmpty(ClickEvent))
            {
                string newEventName = Name + "_Click";
                if (Report.CodeHelper.AddHandler(typeof(EventHandler), newEventName))
                {
                    ClickEvent = newEventName;
                    return true;
                }
                else
                    return false;
            }
            else
            {
                Report.CodeHelper.LocateHandler(ClickEvent);
            }
            return false;
        }

        /// <inheritdoc/>
        public override void OnBeforeInsert(int flags)
        {
            base.OnBeforeInsert(flags);
            try
            {
                Text = BaseName;
            }
            catch
            {
            }
        }
        #endregion
    }
}