//------------------------------------------------------------------------------
// <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
{
  [DesignerCategory("Code")]
  [ToolboxItem(false)]
  [TypeConverter(typeof(ExpandableObjectConverter))]
  public class DataGridTitle : DataAxisGridTitleBar, IGridRowHeightOptionsOwner
  {

    #region private consts
    private static readonly object EventKeyTitleCellMouseDown = new object();
    private static readonly object EventKeyTitleCellMouseMove = new object();
    private static readonly object EventKeyTitleCellMouseUp = new object();
    private static readonly object EventKeyTitleCellMouseClick = new object();
    private static readonly object EventKeyTitleCellMouseDoubleClick = new object();
    private static readonly object EventKeyTitleCellMouseEnter = new object();
    private static readonly object EventKeyTitleCellMouseLeave = new object();
    //private static readonly object EventKeyTitleCellCustomAreaMeasuresNeeded = new object();
    private static readonly object EventKeyTitleCellClientRectNeeded = new object();
    private static readonly object EventKeyTitleCellMouseHover = new object();
    private static readonly object EventKeyCellContextMenuStripNeeded = new object();
    private static readonly object EventKeyTitleCellPaintCustomArea = new object();
    private static readonly object EventKeyCellPaint = new object();

    #endregion private consts

    #region privates
    private bool disposed;
    //private Color foreColor = Color.Empty;
    //private Padding padding = new Padding(0);
    //private readonly Padding defaultPadding = new Padding(3, 2, 3, 4);
    private DataGridTextWrapMode wrapMode = DataGridTextWrapMode.Auto;

    //private readonly GridLine vertLine;
    //private readonly GridLine horzLine;
    //private readonly CellBackFiller backFiller;
    private readonly DataGridMultiTitle multiTitle;

    private bool sortMarkerStyleStored;
    private SortMarkerStyle sortMarkerStyle;
    private readonly DataGridTitleFilter filter;

    private int height;
    private readonly GridRowHeightOptions heightOptions;
    #endregion privates

    public DataGridTitle(DataAxisGrid grid) : base(grid)
    {
      //vertLine = new GridLine(this);
      //horzLine = new GridLine(this);
      //backFiller = new CellBackFiller(this);
      AutoSortMarking = false;
      MultiSortMarking = false;
      filter = new DataGridTitleFilter(Grid);
      heightOptions = new GridRowHeightOptions(this);
      multiTitle = new DataGridMultiTitle(this);
    }

    protected override void Dispose(bool disposing)
    {
      base.Dispose(disposing);

      if (disposed)
        return;
      if (disposing)
      {
        filter.Dispose();
      }
      disposed = true;
    }

    #region design-time properties
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public GridRowHeightOptions HeightOptions
    {
      get
      {
        return heightOptions;
      }
    }

    public SortMarkerStyle SortMarkerStyle
    {
      get
      {
        if (sortMarkerStyleStored)
          return sortMarkerStyle;
        else
          return DefaultSortMarkerStyle();
      }
      set
      {
        if ((sortMarkerStyleStored == false) || (sortMarkerStyle != value))
        {
          sortMarkerStyleStored = true;
          sortMarkerStyle = value;
          if (Grid != null)
            Grid.Invalidate();
        }
      }
    }

    [DefaultValue(false)]
    public bool AutoSortMarking
    { get; set; }

    [DefaultValue(false)]
    public bool MultiSortMarking
    { get; set; }

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public DataGridTitleFilter Filter
    {
      get { return filter; }
    }

    [Browsable(true)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public DataGridMultiTitle MultiTitle
    {
      get { return multiTitle; }
    }

    [DefaultValue(DataGridTextWrapMode.Auto)]
    public DataGridTextWrapMode WrapMode
    {
      get
      {
        return wrapMode;
      }
      set
      {
        if (wrapMode != value)
        {
          wrapMode = value;
          WrapModeChanged();
        }
      }
    }
    #endregion

    #region run-time properties
    [Browsable(false)]
    public int Height
    {
      get
      {
        return height;
      }

      internal set
      {
        height = value;
      }
    }

    [Browsable(false)]
    public bool MouseInTitleRow
    {
      get;
      internal set;
    }

    [Browsable(false)]
    public new DataGridEh Grid
    {
      get { return (DataGridEh)base.Grid; }
    }

    [Browsable(false)]
    public Rectangle ClientBounds
    {
      get
      {
        Rectangle result = Rectangle.Empty;
        if (Visible)
        {
          result.X = Grid.HorzAxis.FixedBoundary;
          result.Y = Grid.VertAxis.GridClientStart;
          result.Width = Grid.HorzAxis.ContraStart - result.X;
          result.Height = Grid.VertAxis.FixedBoundary - result.Y;
        }
        return result;
      }
    }

    [Browsable(false)]
    public DataGridTitleCellMan CellMan
    {
      get
      {
        return Grid.titleCellMan;
      }
    }

    [Browsable(false)]
    public object MouseHolderTitleItem { get; internal set; }
    #endregion

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

    public event EventHandler<DataGridTitleCellPaintEventArgs> CellPaintCustomArea
    {
      add
      {
        this.Events.AddHandler(EventKeyTitleCellPaintCustomArea, value);
      }
      remove
      {
        this.Events.RemoveHandler(EventKeyTitleCellPaintCustomArea, value);
      }
    }

    public event EventHandler<DataGridTitleCellMouseEventArgs> CellMouseDown
    {
      add
      {
        this.Events.AddHandler(EventKeyTitleCellMouseDown, value);
      }
      remove
      {
        this.Events.RemoveHandler(EventKeyTitleCellMouseDown, value);
      }
    }

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

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

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

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

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

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

    //public event EventHandler<DataGridTitleCellCustomAreaMeasuresNeededEventArgs> CustomAreaMeasuresNeeded
    //{
    //  add
    //  {
    //    this.Events.AddHandler(EventKeyTitleCellCustomAreaMeasuresNeeded, value);
    //  }
    //  remove
    //  {
    //    this.Events.RemoveHandler(EventKeyTitleCellCustomAreaMeasuresNeeded, value);
    //  }
    //}

    public event EventHandler<DataGridTitleCellClientAreaNeededEventArgs> CellClientAreaNeeded
    {
      add
      {
        this.Events.AddHandler(EventKeyTitleCellClientRectNeeded, value);
      }
      remove
      {
        this.Events.RemoveHandler(EventKeyTitleCellClientRectNeeded, value);
      }
    }

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

    public event EventHandler<DataGridTitleCellContextMenuStripNeededEventArgs> CellContextMenuStripNeeded
    {
      add
      {
        this.Events.AddHandler(EventKeyCellContextMenuStripNeeded, value);
      }
      remove
      {
        this.Events.RemoveHandler(EventKeyCellContextMenuStripNeeded, value);
      }
    }
    

    //public event EventHandler<DataGridSuperTitleContentRectNeededEventArgs> SuperTitleContentRectNeeded
    //{
    //  add
    //  {
    //    this.Events.AddHandler(EventKeySuperTitleContentRectNeeded, value);
    //  }
    //  remove
    //  {
    //    this.Events.RemoveHandler(EventKeySuperTitleContentRectNeeded, value);
    //  }
    //}

    //public event EventHandler<DataGridSuperTitleFittedHeightNeededEventArgs> SuperTitleFittedHeightNeeded
    //{
    //  add
    //  {
    //    this.Events.AddHandler(EventKeySuperTitleFittedHeightNeeded, value);
    //  }
    //  remove
    //  {
    //    this.Events.RemoveHandler(EventKeySuperTitleFittedHeightNeeded, value);
    //  }
    //}
    #endregion

    #region methods
    //IGridRowHeightOptionsOwner
    void IGridRowHeightOptionsOwner.HeightOptionsChanged(GridRowHeightOptions heightOptions)
    {
      if (Grid != null)
        Grid.RowHeightAutoExpandChanged();
    }

    bool IGridRowHeightOptionsOwner.HeightOptionsDefaultAutoExpand(GridRowHeightOptions heightOptions)
    {
      return false;
    }

    int IGridRowHeightOptionsOwner.HeightOptionsDefaultContentHeight(GridRowHeightOptions heightOptions)
    {
      return 1;
    }

    int IGridRowHeightOptionsOwner.HeightOptionsDefaultMaxContentHeight(GridRowHeightOptions heightOptions)
    {
      return 0;
    }

    GridRowHeightUnit IGridRowHeightOptionsOwner.HeightOptionsDefaultUnit(GridRowHeightOptions heightOptions)
    {
      return GridRowHeightUnit.TextLine;
    }

    //Other
    protected override bool GridLineDefaultVisible(GridLine gl)
    {
      if (Grid == null) return false;

      if (gl == VertLine)
        return Grid.LineOptions.VertLines;
      else if (gl == HorzLine)
        return Grid.LineOptions.HorzLines;
      else
        return false;
    }

    protected override Color GridLineDefaultColor(GridLine gl)
    {
      if (Grid != null)
        return Grid.LineOptions.DarkColor;
      else
        return Color.Empty;
    }

    private SortMarkerStyle DefaultSortMarkerStyle()
    {
      return Grid.GetDrawStyle().GetDefaultSortMarkerStyle();
    }

    protected virtual bool ShouldSerializeSortMarkerStyle()
    {
      return (sortMarkerStyleStored == true);
    }

    public int CalcTitleHeight()
    {
      int th;
      int rowMaxHeight;

      if (Grid.VisibleColumns.Count > 0)
      {
        int colh, maxh;
        maxh = 0;
        foreach (DataGridColumn col in Grid.VisibleColumns)
        {
          colh = col.Title.CalcHeight();
          if (colh > maxh)
            maxh = colh;
        }
        th = maxh;
      }
      else
      {
        Size sz;

        if (HeightOptions.Unit == GridRowHeightUnit.TextLine)
        {
          sz = TextRenderer.MeasureText(EhLibUtils.DisplayGraphicsCash, "0", Font);
          th = sz.Height * HeightOptions.ContentHeight;
          th = th + Padding.Top + Padding.Bottom;
        } 
        else
        {
          th = HeightOptions.ContentHeight;
          th = th + Padding.Top + Padding.Bottom;
        }
      }

      if (HeightOptions.MaxContentHeight > 0)
      {
        if (HeightOptions.Unit == GridRowHeightUnit.TextLine)
        {
          Size sz = TextRenderer.MeasureText(EhLibUtils.DisplayGraphicsCash, "0", Font);
          rowMaxHeight = sz.Height * HeightOptions.MaxContentHeight;
          rowMaxHeight = rowMaxHeight + Padding.Top + Padding.Bottom + 1;
        }
        else
        {
          rowMaxHeight = HeightOptions.MaxContentHeight;
          rowMaxHeight = rowMaxHeight + Padding.Top + Padding.Bottom + 1;
        }

        if (th > rowMaxHeight)
          th = rowMaxHeight;
      }

      return th;
    }

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

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

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

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

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

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

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

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

    //internal void HandleCellCustomAreaMeasuresNeededEvent(DataGridTitleCellCustomAreaMeasuresNeededEventArgs e)
    //{
    //  var eh = this.Events[EventKeyTitleCellCustomAreaMeasuresNeeded] as EventHandler<DataGridTitleCellCustomAreaMeasuresNeededEventArgs>;
    //  if (eh != null)
    //  {
    //    eh(this, e);
    //  }
    //}

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

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

    protected internal virtual void OnCellMouseContextMenuStripNeeded(DataGridTitleCellContextMenuStripNeededEventArgs e)
    {
      DataGridManager.DefaultManager.BuildTitleCellContextMenu(Grid, e);
    }

    private void WrapModeChanged()
    {
      Grid.UpdateRowHeights();
    }

    public void Invalidate()
    {
      Grid.InvalidateRow(0);
    }

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

    protected internal void HandlePaintCustomAreaEvent(DataGridTitleCellPaintEventArgs e)
    {
      var eh = this.Events[EventKeyTitleCellPaintCustomArea] as EventHandler<DataGridTitleCellPaintEventArgs>;

      if (eh != null)
        eh(this, e);
    }
    #endregion
  }
}

