//------------------------------------------------------------------------------
// <copyright file=”*.cs” company=”EhLib Team”>
//     Copyright (c) 2017 Dmitry V. Bolshakov   
// </copyright>
//------------------------------------------------------------------------------

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
using System.Drawing.Drawing2D;

namespace EhLib
{
  [TypeConverter(typeof(ExpandableObjectConverter))]
  [ToolboxItem(false)]
  [DesignerCategory("Code")]
  public class DataVertGridIndicatorTitle : Component
  {
    #region private consts
    private static readonly object EventKeyMouseDown = new object();
    private static readonly object EventKeyMouseMove = new object();
    private static readonly object EventKeyMouseUp = new object();
    private static readonly object EventKeyMouseClick = new object();
    private static readonly object EventKeyMouseDoubleClick = new object();
    private static readonly object EventKeyMouseEnter = new object();
    private static readonly object EventKeyMouseLeave = new object();
    private static readonly object EventKeyCellPaint = new object();
    private static readonly object EventKeyMouseHover = new object();
    #endregion private consts

    #region privates
    private bool pressable = true;
    private bool useGlobalMenu = true;
    private bool showDropDownSign = true;
    private readonly DataVertGridEh grid;

    protected internal bool PersistentDown;
    protected internal GridCoord mouseDownMenuStripCell = new GridCoord(-1, -1);
    #endregion privates

    public DataVertGridIndicatorTitle(DataVertGridEh grid) : base()
    {
      this.grid = grid;
    }

    #region Properties
    [Browsable(false)]
    public DataVertGridEh Grid
    {
      get { return grid; }
    }

    [DefaultValue(true)]
    public bool Pressable
    {
      get { return pressable; }
      set { pressable = value; }
    }

    [DefaultValue(null)]
    public ToolStripDropDown DropDownMenuStrip
    {
      get;
      set;
    }

    [DefaultValue(true)]
    public bool UseGlobalMenu
    {
      get { return useGlobalMenu; }
      set { useGlobalMenu = value; }
    }

    [DefaultValue(true)]
    public bool ShowDropDownSign
    {
      get
      {
        return showDropDownSign;
      }
      set
      {
        if (value != showDropDownSign)
        {
          showDropDownSign = value;
          if (Grid != null)
            Grid.Invalidate();
        }
      }
    }
    #endregion

    #region events
    public event EventHandler<BaseGridCellMouseEventArgs> CellMouseDown
    {
      add
      {
        this.Events.AddHandler(EventKeyMouseDown, value);
      }
      remove
      {
        this.Events.RemoveHandler(EventKeyMouseDown, value);
      }
    }

    public event EventHandler<BaseGridCellMouseEventArgs> CellMouseMove
    {
      add
      {
        this.Events.AddHandler(EventKeyMouseMove, value);
      }
      remove
      {
        this.Events.RemoveHandler(EventKeyMouseMove, value);
      }
    }

    public event EventHandler<BaseGridCellMouseEventArgs> CellMouseUp
    {
      add
      {
        this.Events.AddHandler(EventKeyMouseUp, value);
      }
      remove
      {
        this.Events.RemoveHandler(EventKeyMouseUp, value);
      }
    }

    public event EventHandler<BaseGridCellMouseEventArgs> CellMouseClick
    {
      add
      {
        this.Events.AddHandler(EventKeyMouseClick, value);
      }
      remove
      {
        this.Events.RemoveHandler(EventKeyMouseClick, value);
      }
    }

    public event EventHandler<BaseGridCellMouseEventArgs> CellMouseDoubleClick
    {
      add
      {
        this.Events.AddHandler(EventKeyMouseDoubleClick, value);
      }
      remove
      {
        this.Events.RemoveHandler(EventKeyMouseDoubleClick, value);
      }
    }

    public event EventHandler<BaseGridCellEventArgs> CellMouseEnter
    {
      add
      {
        this.Events.AddHandler(EventKeyMouseEnter, value);
      }
      remove
      {
        this.Events.RemoveHandler(EventKeyMouseEnter, value);
      }
    }

    public event EventHandler<BaseGridCellEventArgs> CellMouseLeave
    {
      add
      {
        this.Events.AddHandler(EventKeyMouseLeave, value);
      }
      remove
      {
        this.Events.RemoveHandler(EventKeyMouseLeave, value);
      }
    }

    public event EventHandler<BaseGridCellMouseEventArgs> CellMouseHover
    {
      add
      {
        this.Events.AddHandler(EventKeyMouseHover, value);
      }
      remove
      {
        this.Events.RemoveHandler(EventKeyMouseHover, value);
      }
    }

    public event EventHandler<BaseGridCellPaintEventArgs> CellPaint
    {
      add
      {
        this.Events.AddHandler(EventKeyCellPaint, value);
      }
      remove
      {
        this.Events.RemoveHandler(EventKeyCellPaint, value);
      }
    }
    #endregion

    internal void BuildAndShowIndicatorTitleMenu(Point ddmPos)
    {
      ToolStripDropDown popupMenu = null;

      if (UseGlobalMenu)
      {
        Grid.Manager.BuildIndicatorTitleMenu(Grid, ref popupMenu);
      }
      else
      {
        popupMenu = DropDownMenuStrip;
      }

      if (popupMenu != null)
      {
        PersistentDown = true;
        Grid.InvalidateCell(0, 0);
        Grid.Update();
        mouseDownMenuStripCell = new GridCoord(-1, -1);
        popupMenu.Closed += MenuStrip_Closed;
        popupMenu.Show(ddmPos);
      }
    }

    protected internal virtual void MenuStrip_Closed(object sender, ToolStripDropDownClosedEventArgs e)
    {
      ((ToolStripDropDown)sender).Closed -= MenuStrip_Closed;
      PersistentDown = false;
      Grid.InvalidateGrid();
      MouseButtons mb = Control.MouseButtons;
      if (mb == MouseButtons.Left)
      {
        Point screenPoint = Cursor.Position;
        Point gridPoint = Grid.PointToClient(screenPoint);
        mouseDownMenuStripCell = Grid.MouseCoord(gridPoint.X, gridPoint.Y);
      }
    }

    protected internal virtual void HandleMouseDownEvent(BaseGridCellMouseEventArgs e)
    {
      var eh = this.Events[EventKeyMouseDown] as EventHandler<BaseGridCellMouseEventArgs>;
      if (eh != null)
        eh(this, e);
    }

    internal void HandleMouseMoveEvent(BaseGridCellMouseEventArgs e)
    {
      var eh = this.Events[EventKeyMouseMove] as EventHandler<BaseGridCellMouseEventArgs>;
      if (eh != null)
        eh(this, e);
    }

    internal void HandleMouseUpEvent(BaseGridCellMouseEventArgs e)
    {
      var eh = this.Events[EventKeyMouseUp] as EventHandler<BaseGridCellMouseEventArgs>;
      if (eh != null)
        eh(this, e);
    }

    internal void HandleMouseClickEvent(BaseGridCellMouseEventArgs e)
    {
      var eh = this.Events[EventKeyMouseClick] as EventHandler<BaseGridCellMouseEventArgs>;
      if (eh != null)
        eh(this, e);
    }

    internal void HandleMouseDoubleClickEvent(BaseGridCellMouseEventArgs e)
    {
      var eh = this.Events[EventKeyMouseDoubleClick] as EventHandler<BaseGridCellMouseEventArgs>;
      if (eh != null)
        eh(this, e);
    }

    internal void HandleMouseEnterEvent(BaseGridCellEnterEventArgs e)
    {
      var eh = this.Events[EventKeyMouseEnter] as EventHandler<BaseGridCellEnterEventArgs>;
      if (eh != null)
      {
        eh(this, e);
      }
    }

    internal void HandleMouseLeaveEvent(BaseGridCellEventArgs e)
    {
      var eh = this.Events[EventKeyMouseLeave] as EventHandler<BaseGridCellEventArgs>;
      if (eh != null)
      {
        eh(this, e);
      }
    }

    internal void HandlePaintEvent(BaseGridCellPaintEventArgs e)
    {
      var eh = this.Events[EventKeyCellPaint] as EventHandler<BaseGridCellPaintEventArgs>;
      if (eh != null)
        eh(this, e);
    }

    internal void HandleMouseHoverEvent(BaseGridCellMouseEventArgs e)
    {
      var eh = this.Events[EventKeyMouseHover] as EventHandler<BaseGridCellMouseEventArgs>;
      if (eh != null)
        eh(this, e);
    }
  }

  public class DataVertGridIndicatorTitleCellMan : BaseGridCellManager
  {
    protected BaseGridFillFixedCellEventArgs StyledPaintArgs = new BaseGridFillFixedCellEventArgs();

    public DataVertGridIndicatorTitleCellMan()
    {

    }

    #region properties
    [Browsable(false)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    public new DataVertGridEh Grid
    {
      get { return (DataVertGridEh)base.Grid; }
      set { base.Grid = value; }
    }
    #endregion

    public override string GetDisplayText(int areaColIndex, int areaRowIndex)
    {
      return null;
    }

    protected internal virtual bool IsPressed(int col, int row, Rectangle paintRect, BasePaintCellStates state, int dataColIndex, int dataRowIndex)
    {
      GridCoord mouseDownCellCoord = Grid.MouseDownCellCoord;

      if (Grid.IndicatorTitle.Pressable)
      {
        if (Grid.IndicatorTitle.PersistentDown)
        {
          return true;
        }
        else if ((col == mouseDownCellCoord.X) &&
                 (row == mouseDownCellCoord.Y) &&
                 (Grid.MouseDownCellCoordPressed == true) &&
                 (Grid.MouseDownButton == MouseButtons.Left) &&
                 (CellContentMouseDown == true)
                )
          return true;
        else
          return false;
      }
      else
      {
        return false;
      }
    }

    protected internal override void HandlePaintEvent(BaseGridCellPaintEventArgs e)
    {
      Grid.IndicatorTitle.HandlePaintEvent(e);
    }

    protected internal override void OnPaintBackground(BaseGridCellPaintEventArgs e)
    {

      Color backColor = Grid.FixedBackColor;

      StyledPaintArgs.CellRect = e.CellClientRect;
      StyledPaintArgs.Graphics = e.Graphics;
      StyledPaintArgs.IsHot = false;
      StyledPaintArgs.IsPressed = IsPressed(e.ColIndex, e.RowIndex, e.CellClientRect, e.State, e.AreaColIndex, e.AreaRowIndex);
      StyledPaintArgs.IsSelected = (e.State & BasePaintCellStates.Selected) != 0;
      StyledPaintArgs.BackColor = backColor;
      StyledPaintArgs.FillStyle = Grid.FixedBackFiller.FillStyle;
      StyledPaintArgs.InnerBorder = Grid.FixedBackFiller.InnerBorder;
      StyledPaintArgs.FillColor = Grid.FixedBackFiller.Color;
      StyledPaintArgs.SecondFillColor = Grid.FixedBackFiller.SecondColor;

      Grid.GetDrawStyle().FillTitleCell(Grid, StyledPaintArgs);
    }

    protected internal override void OnPaintForeground(BaseGridCellPaintEventArgs e)
    {
      Rectangle paintRect = e.CellClientRect;

      Rectangle ddSignRect = new Rectangle(paintRect.Right - 12, paintRect.Top, 12, paintRect.Height);

      bool isPressed = IsPressed(e.ColIndex, e.RowIndex, paintRect, e.State, e.AreaColIndex, e.AreaRowIndex);
      if (isPressed)
        ddSignRect.Offset(1, 1);

      if (Grid.IndicatorTitle.ShowDropDownSign)
        PaintIndicatorDropDownSign(e.Graphics, e.ColIndex, e.RowIndex, ddSignRect, e.State, e.AreaColIndex, e.AreaRowIndex);
    }

    protected internal virtual void PaintIndicatorDropDownSign(Graphics graphics, int col, int row,
      Rectangle paintRect, BasePaintCellStates state, int dataColIndex, int dataRowIndex)
    {
      Color fromColor = EhLibUtils.ApproximateColor(SystemColors.ControlDarkDark, Color.Black, 30);
      Color toColor = EhLibUtils.ApproximateColor(SystemColors.ControlDarkDark, Color.White, 00);
      Point startPos = new Point((paintRect.Right + paintRect.Left - 7) / 2 + 1,
                           (paintRect.Top + paintRect.Bottom - 7) / 2);

      EhLibUtils.FillGradient(graphics, startPos, new Point[]
        { new Point(0, 0), new Point(7, 0),
           new Point(1, 1), new Point(6, 1),
           new Point(2, 2), new Point(5, 2),
           new Point(3, 3), new Point(4, 3)
        },
        fromColor, toColor);

    }

    protected internal override void OnGetCellBorderParams(BaseGridCellBorderEventArgs e)
    {
      base.OnGetCellBorderParams(e);

      if (e.BorderType == GridCellBorderType.Right || e.BorderType == GridCellBorderType.Left)
      {
        GridLine gl = Grid.TitleBar.VertLine;
        e.Visible = gl.Visible;
        e.Color = gl.Color;
        e.Style = gl.Style;
        e.IsExtent = true;
      }
      else
      {
        GridLine gl = Grid.TitleBar.HorzLine;
        e.Visible = gl.Visible;
        e.Color = gl.Color;
        e.Style = gl.Style;
        e.IsExtent = true;
      }
    }

    protected internal override void HandleMouseDownEvent(BaseGridCellMouseEventArgs e)
    {
      Grid.IndicatorTitle.HandleMouseDownEvent(e);
    }

    protected internal override void OnMouseDown(BaseGridCellMouseEventArgs e)
    {
      base.OnMouseDown(e);

      if (e.GridMouseArgs.Button == MouseButtons.Left)
      {
        if (((Grid.IndicatorTitle.DropDownMenuStrip != null) ||
              (Grid.IndicatorTitle.UseGlobalMenu))
            &&
            (Grid.IndicatorTitle.PersistentDown == false))
        {
          Point ddmPos = new Point(e.CellRect.Left, e.CellRect.Bottom);
          ddmPos = Grid.PointToScreen(ddmPos);

          if (Grid.IndicatorTitle.mouseDownMenuStripCell == new GridCoord(0, 0))
          {
            Grid.IndicatorTitle.mouseDownMenuStripCell = new GridCoord(-1, -1);
          }
          else
          {
            Grid.InvalidateCell(e.ColIndex, e.RowIndex);
            Grid.IndicatorTitle.BuildAndShowIndicatorTitleMenu(ddmPos);
          }
        }
      }
    }

    protected internal override void HandleMouseMoveEvent(BaseGridCellMouseEventArgs e)
    {
      Grid.IndicatorTitle.HandleMouseMoveEvent(e);
    }

    protected internal override void HandleMouseUpEvent(BaseGridCellMouseEventArgs e)
    {
      Grid.IndicatorTitle.HandleMouseUpEvent(e);
    }

    protected internal override void HandleMouseClickEvent(BaseGridCellMouseEventArgs e)
    {
      Grid.IndicatorTitle.HandleMouseClickEvent(e);
    }

    protected internal override void HandleMouseDoubleClickEvent(BaseGridCellMouseEventArgs e)
    {
      Grid.IndicatorTitle.HandleMouseDoubleClickEvent(e);
    }

    protected override void HandleMouseEnterEvent(BaseGridCellEnterEventArgs e)
    {
      Grid.IndicatorTitle.HandleMouseEnterEvent(e);
    }

    protected override void HandleMouseLeaveEvent(BaseGridCellLeaveEventArgs e)
    {
      Grid.IndicatorTitle.HandleMouseLeaveEvent(e);
    }

    protected override void HandleMouseHoverEvent(BaseGridCellMouseEventArgs e)
    {
      Grid.IndicatorTitle.HandleMouseHoverEvent(e);
    }

  }

}
