//------------------------------------------------------------------------------
// <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;

namespace EhLib
{

  public enum UpDownButtonId
  {
    Up,
    Down,
  }

  public class UpDownEventArgs : EventArgs
  {
    private readonly UpDownButtonId buttonId;

    public UpDownEventArgs(UpDownButtonId buttonPushed)
    {
      buttonId = buttonPushed;
      Handled = false;
    }

    public UpDownButtonId ButtonId
    {
      get
      {
        return buttonId;
      }
    }
    public bool Handled
    { get; set; }
  }

  public class DownEventArgs : EventArgs
  {

    public DownEventArgs(bool autoRepeat, int nextAutoRepeatDelay)
    {
      this.Handled = false;
      this.AutoRepeat = autoRepeat;
      this.NextAutoRepeatDelay = nextAutoRepeatDelay;
    }

    public bool Handled
    { get; set; }

    public bool AutoRepeat
    { get; set; }

    public int NextAutoRepeatDelay
    { get; set; }
  }

  public class ClickEventArgs : EventArgs
  {
    public ClickEventArgs()
    {
      this.Handled = false;
    }

    public bool Handled
    { get; set; }
  }

  public class EditItemContextPaintEventArgs : PaintEventArgs
  {
    private readonly Rectangle clientRect;
    private readonly bool pressed;
    private readonly bool hot;
    private readonly bool disabled;
    private readonly bool inControlBorderMerging;
    private readonly bool paintBackground;
    private readonly bool paintForeground;

    public EditItemContextPaintEventArgs(Rectangle clientRect, bool pressed, bool hot, bool disabled,
      bool drawBackground, bool drawForeground, bool inControlBorderMerging, Graphics graphics, Rectangle clipRect
    ) : base(graphics, clipRect)
    {
      this.clientRect = clientRect;
      this.pressed = pressed;
      this.hot = hot;
      this.disabled = disabled;
      this.inControlBorderMerging = inControlBorderMerging;
      this.paintBackground = drawBackground;
      this.paintForeground = drawForeground;
    }

    public Rectangle ClientRect
    {
      get { return clientRect; }
    }

    public bool Pressed
    {
      get { return pressed; }
    }

    public bool Hot
    {
      get { return hot; }
    }

    public bool Disabled
    {
      get { return disabled; }
    }

    public bool InControlBorderMerging
    {
      get { return inControlBorderMerging; }
    }

    public bool PaintBackground
    {
      get { return paintBackground; }
    }

    public bool PaintForeground
    {
      get { return paintForeground; }
    }

  }

  public class VisibleStateRequestedEventArgs : EventArgs
  {
    public VisibleStateRequestedEventArgs(bool visible)
    {
      this.Visible = visible;
    }

    public bool Visible
      { get; set; }
  }

  public delegate void UpDownEventHandler(object sender, UpDownEventArgs e);
  public delegate void DownEventHandler(object sender, DownEventArgs e);
  public delegate void ClickEventHandler(object sender, ClickEventArgs e);
  public delegate void VisibleStateRequestedEventHandler(object sender, VisibleStateRequestedEventArgs e);

  [System.ComponentModel.DesignerCategory("Code")]
  [DesignTimeVisible(false)]
  [TypeConverter(typeof(ExpandableObjectConverter))]
  //[Designer("EhLib.Design.InEditControlDesigner" + EhLibUtils.EhLibDesignDesignerVersionInfo)]
  [ToolboxItem(false)]
  //public class InEditControl : Control
  public class EditItem : Component
  //public class InEditControl
  {

    #region private consts
    private static readonly object EventKeyDown = new object();
    #endregion private consts

    #region fields
    private int width = 15;
    bool widthStored;

    private BaseEditBoxEh editControl;
    private EditItemControl inEditWinControl;
    private bool defaultAction = true;

    //private KeyEventHandler onKeyDown;
    private UpDownEventHandler upDownEventHandler;
    //private DownEventHandler downEventHandler;
    private ClickEventHandler clickEventHandler;
    private bool visibleStored;
    private bool visible;
    private EventHandler editItemChanged;
    private VisibleStateRequestedEventHandler defaultVisibleStateRequested;
    #endregion fields

    #region constructor
    public EditItem()
    {
      //this.SetStyle(ControlStyles.Selectable, false);
    }

    #endregion constructor

    #region properties
    protected internal EditItemControl InEditWinControl
    {
      get
      {
        if (inEditWinControl == null)
          inEditWinControl = CreateInEditWinControl();
        return inEditWinControl;
      }
    }

    public BaseEditBoxEh EditControl
    {
      get { return editControl; }
      internal set { editControl = value; }
    }

    public int Width
    {
      get
      {
        if (widthStored)
          return width;
        else
          return width;
      }
      set
      {
        if ((widthStored == false) || (value != width))
        {
          widthStored = true;
          width = value;
          WidthChanged();
        }
      }
    }

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

    public bool Visible
    {
      get
      {
        if (visibleStored)
          return visible;
        else
          return DefaultVisible();
      }
      set
      {
        if (!visibleStored || value != visible)
        {
          visibleStored = true;
          visible = value;
          NotifyEditItemChanged();
        }
      }
    }
    #endregion properties

    #region run-time properties
    [Browsable(false)]
    public virtual bool SupportInControlBorderMerging
    {
      get
      {
        return false;
      }
    }

    [Browsable(false)]
    public virtual int MaxHeight
    {
      get
      {
        return Width * 3 / 2;
      }
    }
    #endregion run-time properties

    #region events
    //public event KeyEventHandler KeyDown
    //{
    //  add { onKeyDown += value; }
    //  remove { onKeyDown -= value; }
    //}

    public event UpDownEventHandler UpDown
    {
      add
      {
        upDownEventHandler += value;
      }
      remove
      {
        upDownEventHandler -= value;
      }
    }

    public event ClickEventHandler Click
    {
      add
      {
        clickEventHandler += value;
      }
      remove
      {
        clickEventHandler -= value;
      }
    }

    //public event DownEventHandler Down
    //{
    //  add
    //  {
    //    downEventHandler += value;
    //  }
    //  remove
    //  {
    //    downEventHandler -= value;
    //  }
    //}

    public event DownEventHandler Down
    {
      add
      {
        this.Events.AddHandler(EventKeyDown, value);
      }
      remove
      {
        this.Events.RemoveHandler(EventKeyDown, value);
      }
    }

    public event EventHandler EditItemChanged
    {
      add
      {
        this.editItemChanged += value;
      }

      remove
      {
        this.editItemChanged -= value;
      }
    }

    public event VisibleStateRequestedEventHandler DefaultVisibleStateRequested
    {
      add
      {
        this.defaultVisibleStateRequested += value;
      }

      remove
      {
        this.defaultVisibleStateRequested -= value;
      }
    }
    #endregion  

    #region public methods
    public virtual bool IntegratedInBorder()
    {
      return false;
    }

    public virtual void ResetWidth()
    {
      if (widthStored)
      {
        widthStored = false;
        WidthChanged();
      }
    }

    public virtual int DefaultWidth()
    {
      return SystemInformation.VerticalScrollBarWidth;
    }

    public virtual void DefaultHandleDownAction(DownEventArgs e)
    {
      if (e.Handled) return;
      if (DefaultAction)
        EditControl.HandleInEditControlDownAction(this, e);
    }

    public virtual void DefaultHandleClickAction(ClickEventArgs e)
    {
      if (e.Handled) return;
      if (DefaultAction)
        EditControl.HandleInEditControlClickAction(this, e);
  }

    public virtual bool IsDropDown()
    {
      return false;
    }
    #endregion public methods

    #region intenal methods
    protected virtual EditItemControl CreateInEditWinControl()
    {
      return new EditItemControl(this);
    }

    protected void NotifyEditItemChanged()
    {
      if (editItemChanged != null)
        editItemChanged(this, EventArgs.Empty);

      //if (editControl != null)
      //  editControl.InEditControlChanged(this);
    }

    protected void WidthChanged()
    {
      NotifyEditItemChanged();
    }

    protected virtual bool ShouldSerializeWidth()
    {
      return (widthStored == true);
    }

    protected internal virtual void OnUpDown(UpDownEventArgs e)
    {
      if (upDownEventHandler != null)
        upDownEventHandler(this, e);
      if (!e.Handled)
        EditControl.OnProcessInEditUpDownButton(e);
    }

    protected internal virtual void OnDown(DownEventArgs e)
    {
      var eh = this.Events[EventKeyDown] as DownEventHandler;
      if (eh != null)
        eh(this, e);

      //if (downEventHandler != null)
      //  downEventHandler(this, e);
      if (!e.Handled)
        DefaultHandleDownAction(e);
    }

    protected internal virtual void OnClick(ClickEventArgs e)
    {
      if (clickEventHandler != null)
        clickEventHandler(this, e);
      if (!e.Handled)
        DefaultHandleClickAction(e);
    }

    protected internal virtual bool ProcessCmdKey(ref Message msg, Keys keyData)
    {
      return false;
    }

    protected virtual bool DefaultVisible()
    {
      if (defaultVisibleStateRequested != null)
      {
        VisibleStateRequestedEventArgs e = new VisibleStateRequestedEventArgs(true);
        defaultVisibleStateRequested(this, e);
        return e.Visible;
      }
      else if (editControl != null)
      {
        return editControl.IsInEditControlDefaultVisible(this);
      }
      else
        return true;
    }

    protected bool ShouldSerializeVisible()
    {
      return (visibleStored == true);
    }

    protected void ResetVisible()
    {
      if (visibleStored)
      {
        visibleStored = false;
        NotifyEditItemChanged();
      }
    }

    protected internal virtual void Paint(EditItemContextPaintEventArgs e)
    {
      e.Graphics.DrawRectangle(new Pen(Color.Red), e.ClientRect);
    }

    #endregion intenal methods

  }

  [DesignTimeVisible(false)]
  //[ToolboxItem(false)]
  public class EditItemControl : Control
  {
    private readonly EditItem inEditControl;

    #region constructor
    public EditItemControl(EditItem inEditControl)
    {
      this.inEditControl = inEditControl;
      SetStyle(ControlStyles.Selectable, false);
    }

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

    #endregion constructor

    #region properties
    protected internal EditItem InEditControl
    {
      get { return inEditControl; }
    }

    protected internal bool InControlBorderMerging
      { get; set; }
    #endregion properties

    protected override void OnPaint(PaintEventArgs e)
    {
      Rectangle btnRect = ClientRectangle;
      ButtonRenderer.DrawButton(e.Graphics, btnRect, PushButtonState.Normal);
    }

  }
}
