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

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

namespace EhLib
{

  [DataAxisGridDataCellDesignTimeVisibleAttribute(true)]
  public class DataAxisGridButtonDataCell : DataAxisGridButtonBaseCell
  {

    #region internal
    protected internal int HotButtonDataRow = -1;

    private FlatStyle flatStyle = FlatStyle.Standard;
    private string text;
    private bool useColumnTextForButtonValue;
    private bool buttonPaddingStored;
    private Padding buttonPadding = new Padding(0);
    private Padding defaultButtonPadding = new Padding(2, 3, 2, 3);
    //protected bool downState = false;
    #endregion

    #region properties
    [DefaultValue(FlatStyle.Standard)]
    public FlatStyle FlatStyle
    {
      get
      {
        return this.flatStyle;
      }
      set
      {
        if (this.flatStyle != value)
        {
          flatStyle = value;
          if (Grid != null)
            Grid.InvalidateGrid();
        }
      }
    }

    public string Text
    {
      get
      {
        return this.text;
      }
      set
      {
        if (value != this.text)
        {
          this.text = value;
          if (Grid != null)
            Grid.InvalidateGrid();
        }
      }
    }

    [DefaultValue(false)]
    public bool UseColumnTextForButtonValue
    {
      get
      {
        return this.useColumnTextForButtonValue;
      }
      set
      {
        if (this.useColumnTextForButtonValue != value)
        {
          this.useColumnTextForButtonValue = value;
          if (Grid != null)
            Grid.InvalidateGrid();
        }
      }
    }
    #endregion

    #region runtime properties
    [Browsable(false)]
    public new bool DownState
    {
      get
      {
        return base.DownState;
      }
      set
      {
        if (value != base.DownState)
        {
          base.DownState = value;
          if (Grid != null)
            Grid.InvalidateGrid();
        }
      }
    }

    public Padding ButtonPadding
    {
      get
      {
        if (buttonPaddingStored)
          return buttonPadding;
        else
          return DefaultButtonPadding();
      }
      set
      {
        buttonPadding = value;
        buttonPaddingStored = true;
        ButtonPaddingChanged();
      }
    }

    #endregion

    #region methods
    //ButtonPadding
    public virtual void ButtonPaddingChanged()
    {
      if (Grid != null)
        Grid.UpdateBaseFixedBands();
    }

    public virtual Padding DefaultButtonPadding()
    {
      if (Grid != null)
        return defaultButtonPadding;
      else
        return Padding.Empty;
    }

    public virtual bool ShouldSerializeButtonPadding()
    {
      return (buttonPaddingStored == true);
    }

    public virtual void ResetButtonPadding()
    {
      buttonPaddingStored = false;
      ButtonPaddingChanged();
    }

    //Other
    public override Padding DefaultPadding()
    {
      if (Grid != null)
        return GetPaddingForSidePadding(Grid.GetDataCellSidePadding());
      else
        return Padding.Empty;
    }

    protected Padding GetPaddingForSidePadding(Padding sidePadding)
    {
      // ReSharper disable once UseObjectOrCollectionInitializer
      var result = new Padding();

      result.Left = Math.Max(sidePadding.Left, sidePadding.Right);
      result.Right = result.Left;
      result.Top = sidePadding.Top;
      result.Bottom = sidePadding.Bottom;

      return result;
    }

    protected internal virtual void SetHotButtonDataRow(bool isHot, int colIndex, int rowIndex, int dataColIndex, int dataRowIndex)
    {
      if (dataRowIndex == -1 && isHot == false && HotButtonDataRow != -1)
      {
        HotButtonDataRow = -1;
        Grid.InvalidateCell(colIndex, rowIndex);
      }
      else if (HotButtonDataRow != dataRowIndex && isHot)
      {
        HotButtonDataRow = dataRowIndex;
        Grid.InvalidateCell(colIndex, rowIndex);
      }
      else if (HotButtonDataRow == dataRowIndex && !isHot)
      {
        HotButtonDataRow = -1;
        Grid.InvalidateCell(colIndex, rowIndex);
      }
    }

    public override string GetDisplayText(PropertyAxisBar propAxisBar, object listItemBar)
    {
      if (UseColumnTextForButtonValue)
        return Text;
      else
        return base.GetDisplayText(propAxisBar, listItemBar);
    }

    protected override void PaintForeground(DataAxisGridDataCellPaintEventArgs e)
    {
      Rectangle buttonPaintRect = e.CellRect;
      PushButtonState buttonState;

      if (DownState && (Grid.CurrentDataRowIndex == e.AreaRowIndex))
        buttonState = PushButtonState.Pressed;
      else if (HotButtonDataRow == e.AreaRowIndex)
        buttonState = PushButtonState.Hot;
      else if (Grid.Col == e.ColIndex &&
               Grid.Row == e.RowIndex &&
               Grid.Focused)
        buttonState = PushButtonState.Default;
      else
        buttonState = PushButtonState.Normal;

      buttonPaintRect.X = buttonPaintRect.X + Padding.Left;
      buttonPaintRect.Y = buttonPaintRect.Y + Padding.Top;
      buttonPaintRect.Width = buttonPaintRect.Width - Padding.Left - Padding.Right;
      buttonPaintRect.Height = buttonPaintRect.Height - Padding.Top - Padding.Bottom;

      //ControlPaint.DrawBorder(graphics, ButtonDrawRect, SystemColors.Control, ButtonBorderStyle.Outset);
      ButtonRenderer.DrawButton(e.Graphics, buttonPaintRect, buttonState);

      //      graphics.DrawImage(img, ImageDrawRect, 0, 0, img.Width, img.Height, GraphicsUnit.Pixel);
      DrawButtonForeground(e, buttonPaintRect);
    }

    protected virtual void DrawButtonForeground(DataAxisGridDataCellPaintEventArgs e, Rectangle buttonDrawRect)
    {
      Color fForeColor = Grid.ForeColor;
      bool clipped = false;
      Region clientClip = null;

      if (DownState && (Grid.CurrentDataRowIndex == e.DataRowIndex))
      {
        clientClip = e.Graphics.Clip;
        e.Graphics.SetClip(buttonDrawRect, CombineMode.Intersect);
        clipped = true;
        buttonDrawRect.Offset(new Point(1, 1));
      }

      TextFormatFlags fmtFlags = TextFormatFlags.Left |
                                  TextFormatFlags.VerticalCenter |
                                  TextFormatFlags.PreserveGraphicsClipping |
                                  TextFormatFlags.HorizontalCenter;
      string text = GetDisplayText(e.PropAxisBar, e.ListItemBar);
      if (text != null)
        TextRenderer.DrawText(e.Graphics, text, Font, buttonDrawRect, fForeColor, fmtFlags);

      if (clipped)
      {
        e.Graphics.Clip = clientClip;
        buttonDrawRect.Offset(new Point(-1, -1));
      }
    }

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

      Rectangle cellBounds = e.CellRect;
      cellBounds.Location = Point.Empty;

      Rectangle buttonRect = EhLibUtils.TrimPadding(cellBounds, Padding);

      if (buttonRect.Contains(e.InCellX, e.InCellY))
        DownState = true;
    }

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

      Rectangle cellBounds = e.CellRect;
      cellBounds.Location = Point.Empty;

      Rectangle buttonRect = EhLibUtils.TrimPadding(cellBounds, Padding);

      if (buttonRect.Contains(e.InCellX, e.InCellY))
        SetHotButtonDataRow(true, e.ColIndex, e.RowIndex, e.AreaColIndex, e.AreaRowIndex);
      else
        SetHotButtonDataRow(false, e.ColIndex, e.RowIndex, e.AreaColIndex, e.AreaRowIndex);
    }

    protected internal override void OnMouseUp(BaseGridCellMouseEventArgs e)
    {
      int dataColIndex;
      int dataRowIndex;

      GridCellPosToAreaCellPos(e.ColIndex, e.RowIndex, out dataColIndex, out dataRowIndex);
      if (DownState &&
          (e.InCellX >= 0) &&
          (e.InCellY >= 0) &&
          (e.InCellX < e.CellRect.Width) &&
          (e.InCellY < e.CellRect.Height))
      {

        PropertyAxisBar propAxisBar;
        object listItemBar;
        AxisObjectsByDataColRowIndex(dataColIndex, dataRowIndex, out propAxisBar, out listItemBar);

        DataAxisGridDataCellEventArgs de;
        if (PropAxisBar != null)
          de = PropAxisBar.CreateDataCellEventArgs(e.ColIndex, e.RowIndex, dataColIndex, dataRowIndex, e.CellRect, propAxisBar, listItemBar, this);
        else
          de = CreateDataCellEventArgs(e.ColIndex, e.RowIndex, dataColIndex, dataRowIndex, e.CellRect, propAxisBar, listItemBar, this);

        Grid.OnDataCellClick(de);
      }
      base.OnMouseUp(e);
      DownState = false;
    }

    protected internal override void OnMouseEnter(BaseGridCellEnterEventArgs e)
    {
      Grid.InvalidateCell(e.ColIndex, e.RowIndex);
      base.OnMouseEnter(e);
    }

    protected internal override void OnMouseLeave(BaseGridCellLeaveEventArgs e)
    {
      Grid.InvalidateCell(e.ColIndex, e.RowIndex);
      base.OnMouseLeave(e);
      SetHotButtonDataRow(false, e.ColIndex, e.RowIndex, e.AreaColIndex, e.AreaRowIndex);
    }

    protected internal override int CalcDefaultRowHeight()
    {
      int th;

      th = EhLibUtils.GetFontHeight(Font);
      th = th + Padding.Top + Padding.Bottom + ButtonPadding.Top + ButtonPadding.Bottom;
      return th;
    }

    protected internal override int CalcCellHeight(PropertyAxisBar propAxisBar, object listItemBar, int cellWidth)
    {
      int th;

      if (HeightOptions.Unit == GridRowHeightUnit.TextLine)
      {
        th = EhLibUtils.GetFontHeight(Font) * HeightOptions.ContentHeight;
        th = th + Padding.Top + Padding.Bottom + ButtonPadding.Top + ButtonPadding.Bottom;
      }
      else
      {
        th = HeightOptions.ContentHeight;
        th = th + Padding.Top + Padding.Bottom + ButtonPadding.Top + ButtonPadding.Bottom;
      }

      return th;
    }

    #endregion

  }

}
