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

namespace FastReport.AdvMatrix
{
    public partial class AdvMatrixObject
    {
        #region Private Methods
        private void DrawHeaderArea(FRPaintEventArgs e)
        {
            TableCell c = this[Data.Rows.Size, Data.Columns.Size];
            Pen p = e.Cache.GetPen(Color.Black, 1 * e.ScaleX, DashStyle.Dash);
            e.Graphics.DrawRectangle(p, (c.AbsLeft - 1) * e.ScaleX, AbsTop * e.ScaleY, 2 * e.ScaleX, Height * e.ScaleY);
            e.Graphics.DrawRectangle(p, AbsLeft * e.ScaleX, (c.AbsTop - 1) * e.ScaleY, Width * e.ScaleY, 2 * e.ScaleY);
        }

        private void DrawGroups(FRPaintEventArgs e, MatrixHeader header)
        {
            Pen groupPen = e.Cache.GetPen(Color.Orange, 3 * e.ScaleX, DashStyle.Solid);
            Pen topNPen = e.Cache.GetPen(Color.Red, 3 * e.ScaleX, DashStyle.Solid);

            foreach (HeaderDescriptor d in header.Descriptor.AllItems)
            {
                TableCell c = d.TemplateCell;
                if (c != null && d.IsGroup)
                {
                    Pen p = d.TopN.Count != 0 && d.TopNItemsPresent() ? topNPen : groupPen;
                    if (d.IsColumn)
                    {
                        e.Graphics.DrawLines(p, new PointF[] {
                            new PointF(c.AbsLeft * e.ScaleX, (c.AbsTop + 6) * e.ScaleY), new PointF(c.AbsLeft * e.ScaleX, c.AbsTop * e.ScaleY),
                            new PointF(c.AbsRight * e.ScaleX, c.AbsTop * e.ScaleY), new PointF(c.AbsRight * e.ScaleX, (c.AbsTop + 6) * e.ScaleY)
                        });
                    }
                    else
                    {
                        e.Graphics.DrawLines(p, new PointF[] {
                            new PointF((c.AbsLeft + 6) * e.ScaleX, c.AbsBottom * e.ScaleY), new PointF(c.AbsLeft * e.ScaleX, c.AbsBottom * e.ScaleY),
                            new PointF(c.AbsLeft * e.ScaleX, c.AbsTop * e.ScaleY), new PointF((c.AbsLeft + 6) * e.ScaleX, c.AbsTop * e.ScaleY)
                        });
                    }
                }
            }
        }

        private void DrawTopNMarks(FRPaintEventArgs e, MatrixHeader header)
        {
            foreach (HeaderDescriptor d in header.Descriptor.AllItems)
            {
                TableCell c = d.TemplateCell;
                if (c != null && d.IsTopNItem)
                {
                    e.Graphics.DrawImage(Report.Designer.GetImage(99), (int)((c.AbsRight - 14) * e.ScaleX), (int)((c.AbsTop + 2) * e.ScaleY), 16 * e.ScaleX, 16 * e.ScaleY);
                }
            }
        }

        private void DrawFrame(FRPaintEventArgs e, ComponentBase c, Color color)
        {
            Pen p = e.Cache.GetPen(color, 3 * e.ScaleX, DashStyle.Solid);
            e.Graphics.DrawRectangle(p, c.AbsLeft * e.ScaleX, c.AbsTop * e.ScaleY, c.Width * e.ScaleX, c.Height * e.ScaleY);
        }

        private void DrawDragIndicator(FRPaintEventArgs e)
        {
            dragInfo.TargetCell.DrawDragAcceptFrame(e, Color.Red);

            if (dragInfo.Indicator.Width > 0 || dragInfo.Indicator.Height > 0)
            {
                IGraphics g = e.Graphics;
                int left = (int)Math.Round((dragInfo.Indicator.Left + AbsLeft) * e.ScaleX);
                int top = (int)Math.Round((dragInfo.Indicator.Top + AbsTop) * e.ScaleY);
                int right = (int)Math.Round(dragInfo.Indicator.Width * e.ScaleX) + left;
                int bottom = (int)Math.Round(dragInfo.Indicator.Height * e.ScaleY) + top;

                Pen p = e.Cache.GetPen(Color.Red, 1 * e.ScaleX, DashStyle.Dot);
                g.DrawLine(p, left, top, right, bottom);

                p = Pens.Red;
                Brush b = Brushes.Red;

                int n = (int)(5 * e.ScaleX);
                if (dragInfo.Indicator.Width == 0)
                {
                    Point[] poly = new Point[] {
                        new Point(left, top),
                        new Point(left - n, top - n),
                        new Point(left + n, top - n),
                        new Point(left, top) };
                    g.FillPolygon(b, poly);
                    g.DrawPolygon(p, poly);

                    poly = new Point[] {
                        new Point(left, bottom),
                        new Point(left - n, bottom + n),
                        new Point(left + n, bottom + n),
                        new Point(left, bottom) };
                    g.FillPolygon(b, poly);
                    g.DrawPolygon(p, poly);
                }
                else
                {
                    Point[] poly = new Point[] {
                        new Point(left, top),
                        new Point(left - n, top - n),
                        new Point(left - n, top + n),
                        new Point(left, top) };
                    g.FillPolygon(b, poly);
                    g.DrawPolygon(p, poly);

                    poly = new Point[] {
                        new Point(right, top),
                        new Point(right + n, top - n),
                        new Point(right + n, top + n),
                        new Point(right, top) };
                    g.FillPolygon(b, poly);
                    g.DrawPolygon(p, poly);
                }
            }
        }

        private void HighlightButtonLinkedItems(FRPaintEventArgs e)
        {
            if (Report.Designer.SelectedObjects.Count == 1)
            {
                MatrixCollapseButton btn = Report.Designer.SelectedObjects[0] as MatrixCollapseButton;
                if (btn != null && btn.Cell != null)
                {
                    HeaderDescriptor descr = btn.Cell.GetHeaderDescriptor();
                    if (descr != null)
                    {
                        foreach (HeaderDescriptor d in descr.Root.AllItems)
                        {
                            if (d.VisibleToggledBy == btn.Name)
                                DrawFrame(e, d.TemplateCell, Color.FromArgb(80, Color.Red));
                        }
                    }
                }
            }
        }

        private void HighlightLinkedButton(FRPaintEventArgs e, TableCell cell)
        {
            HeaderDescriptor descr = cell.GetHeaderDescriptor();
            if (descr != null)
            {
                MatrixCollapseButton btn = Report.FindObject(descr.VisibleToggledBy) as MatrixCollapseButton;
                if (btn != null)
                    DrawFrame(e, btn, Color.FromArgb(80, Color.Red));
            }
        }

        private void HighlightTopNItems(FRPaintEventArgs e, TableCell cell)
        {
            HeaderDescriptor descr = cell.GetHeaderDescriptor();
            if (descr != null && descr.TopN.Count > 0 && descr.TopNItemsPresent())
            {
                Color c = Color.FromArgb(80, Color.Red);
                DrawFrame(e, descr.TopN.Total.Descriptor.TemplateCell, c);
                DrawFrame(e, descr.TopN.Others.Descriptor.TemplateCell, c);
                DrawFrame(e, descr.TopN.OthersTotal.Descriptor.TemplateCell, c);
            }
        }

        #endregion

        #region Public Methods
        /// <inheritdoc/>
        public override void Draw(FRPaintEventArgs e)
        {
            if (IsDesigning && !Report.Designer.IsPreviewPageDesigner)
                UpdateDescriptors();

            base.Draw(e);
            if (!IsDesigning || (IsDesigning && Report.Designer.IsPreviewPageDesigner))
                return;

            if (Data.Columns.Descriptor.IsEmpty() && Data.Rows.Descriptor.IsEmpty())
            {
                TextRenderer.DrawText(e.Graphics.Graphics, Res.Get("ComponentsMisc,AdvMatrix,NewItems"),
                    e.Cache.GetFont(DrawUtils.DefaultFont.FontFamily, 8 * e.ScaleX * 96 / DrawUtils.ScreenDpi, FontStyle.Regular),
                    new Rectangle((int)(AbsLeft * e.ScaleX), (int)(AbsTop * e.ScaleY), (int)(Width * e.ScaleX), (int)(Height * e.ScaleY)), Color.Black,
                    TextFormatFlags.WordBreak | TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter | TextFormatFlags.NoPrefix);
            }
            else
            {
                if (IsSelected)
                {
                    DrawHeaderArea(e);
                    DrawGroups(e, Data.Columns);
                    DrawGroups(e, Data.Rows);
                    DrawTopNMarks(e, Data.Columns);
                    DrawTopNMarks(e, Data.Rows);
                }
                HighlightButtonLinkedItems(e);

                if (dragInfo.SelectedCell != null)
                {
                    DrawFrame(e, dragInfo.SelectedCell, Color.Black);
                    HighlightTopNItems(e, dragInfo.SelectedCell);
                    HighlightLinkedButton(e, dragInfo.SelectedCell);
                }
            }

            if (dragInfo.TargetCell != null)
                DrawDragIndicator(e);
        }

        #endregion
    }
}