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

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;

namespace EhLib
{

  //public enum EditBoxBorderStyle
  //{
  //  None,
  //  FixedSingle,
  //  Fixed3D,
  //  Custom
  //}

  [TypeConverter(typeof(ExpandableObjectConverter))]
  public class EditBoxBorder
  {
    #region privates
    private ControlBorderStyle style = ControlBorderStyle.Fixed3D;
    private Color normalColor = Color.Empty;
    private Color hotColor = Color.Empty;
    private Color selectedColor = Color.Empty;
    private Color disabledColor = Color.Empty;
    private bool normalColorStored;
    private bool hotColorStored;
    private bool selectedColorStored;
    private bool disabledColorStored;

    private EventHandler borderStateChanged;
    #endregion

    #region constructor
    public EditBoxBorder()
    {
    }
    #endregion

    #region design-time properties
    [DefaultValue(ControlBorderStyle.Fixed3D)]
    public ControlBorderStyle Style
    {
      get
      {
        return style;
      }

      set
      {
        if (style != value)
        {
          style = value;
          OnBorderStateChanged();
        }
      }
    }

    public Color NormalColor
    {
      get
      {
        if (normalColorStored)
          return normalColor;
        else
          return DefaultNormalColor();
      }

      set
      {
        if ((normalColorStored == false) || (normalColor != value))
        {
          normalColorStored = true;
          normalColor = value;
          NormalColorChanged();
        }
      }
    }

    public Color HotColor
    {
      get
      {
        if (hotColorStored)
          return hotColor;
        else
          return DefaultHotColor();
      }

      set
      {
        if ((hotColorStored == false) || (hotColor != value))
        {
          hotColorStored = true;
          hotColor = value;
          HotColorChanged();
        }
      }
    }

    public Color SelectedColor
    {
      get
      {
        if (selectedColorStored)
          return selectedColor;
        else
          return DefaultSelectedColor();
      }

      set
      {
        if ((selectedColorStored == false) || (selectedColor != value))
        {
          selectedColorStored = true;
          selectedColor = value;
          SelectedColorChanged();
        }
      }
    }

    public Color DisabledColor
    {
      get
      {
        if (disabledColorStored)
          return disabledColor;
        else
          return DefaultDisabledColor();
      }

      set
      {
        if ((disabledColorStored == false) || (disabledColor != value))
        {
          disabledColorStored = true;
          disabledColor = value;
          DisabledColorChanged();
        }
      }
    }

    [Browsable(false)]
    public int BorderWidth
    {
      get
      {
        if (Style == ControlBorderStyle.Fixed3D)
          return 2;
        else if (Style == ControlBorderStyle.None)
          return 0;
        else
          return 1;
      }
    }
    #endregion

    #region methods

    //NormalColor
    private void NormalColorChanged()
    {
      OnBorderStateChanged();
    }

    private Color DefaultNormalColor()
    {
      return SystemColors.WindowFrame;
    }

    protected virtual bool ShouldSerializeNormalColor()
    {
      return normalColorStored;
    }

    public virtual void ResetNormalColor()
    {
      if (normalColorStored)
      {
        normalColorStored = false;
        NormalColorChanged();
      }
    }

    //HotColor
    private void HotColorChanged()
    {
      OnBorderStateChanged();
    }

    private Color DefaultHotColor()
    {
      return SystemColors.WindowText;
    }

    protected virtual bool ShouldSerializeHotColor()
    {
      return hotColorStored;
    }

    public virtual void ResetHotColor()
    {
      if (hotColorStored)
      {
        hotColorStored = false;
        HotColorChanged();
      }
    }

    //SelectedColor
    private void SelectedColorChanged()
    {
      OnBorderStateChanged();
    }

    private Color DefaultSelectedColor()
    {
      return SystemColors.HotTrack;
    }

    protected virtual bool ShouldSerializeSelectedColor()
    {
      return selectedColorStored;
    }

    public virtual void ResetSelectedColor()
    {
      if (selectedColorStored)
      {
        selectedColorStored = false;
        SelectedColorChanged();
      }
    }

    //DisabledColor
    private void DisabledColorChanged()
    {
      OnBorderStateChanged();
    }

    private Color DefaultDisabledColor()
    {
      return SystemColors.ControlLight;
    }

    protected virtual bool ShouldSerializeDisabledColor()
    {
      return disabledColorStored;
    }

    public virtual void ResetDisabledColor()
    {
      if (disabledColorStored)
      {
        disabledColorStored = false;
        DisabledColorChanged();
      }
    }

    //Other
    private void OnBorderStateChanged()
    {
      if (borderStateChanged != null)
      {
        borderStateChanged(this, EventArgs.Empty);
      }
    }

    internal void BorderSideChanged(ControlBorderSide controlBorderSide)
    {
      OnBorderStateChanged();
    }

    public virtual void Paint(Graphics graphics, Rectangle borderRect, TextBoxState state)
    {
      Rectangle br = borderRect;

      if (this.Style == ControlBorderStyle.None)
      {
        //return;
        EhLibUtils.DoNothing();
      }
      else if (this.Style == ControlBorderStyle.Fixed3D || this.Style == ControlBorderStyle.FixedSingle)
      {
        BorderStyle bdrStyle = ControlBorderStyleToBorderStyle(Style);
        EhLibDrawStyle.DefaultTextBoxDrawStyle.DrawTextBoxFrame(graphics, br, state, null, bdrStyle);
      }
      else if (this.Style == ControlBorderStyle.Custom)
      {
        Color brdColor = GetBorderColor(state);
        br.Width = br.Width - 1;
        br.Height = br.Height - 1;
        using (var pen = new Pen(brdColor))
        {
          graphics.DrawRectangle(pen, br);
        }
      }

    }

    private Color GetBorderColor(TextBoxState state)
    {
      if (state == TextBoxState.Normal)
        return NormalColor;
      else if (state == TextBoxState.Hot)
        return HotColor;
      else if (state == TextBoxState.Selected)
        return SelectedColor;
      else if (state == TextBoxState.Readonly)
        return NormalColor;
      else if (state == TextBoxState.Disabled)
        return DisabledColor;
      else
        return NormalColor;
    }

    public BorderStyle ControlBorderStyleToBorderStyle(ControlBorderStyle borderStyle)
    {
      if (borderStyle == ControlBorderStyle.Fixed3D)
        return BorderStyle.Fixed3D;
      else if (borderStyle == ControlBorderStyle.FixedSingle)
        return BorderStyle.FixedSingle;
      else
        throw new ArgumentNullException("ctlBorderStyle");
    }

    public void ExcludeBorderRect(ref Rectangle controlRect)
    {
      controlRect.X = controlRect.X + BorderWidth;
      controlRect.Y = controlRect.Y + BorderWidth;
      controlRect.Width = controlRect.Width - BorderWidth - BorderWidth;
      controlRect.Height = controlRect.Height - BorderWidth - BorderWidth;
    }

    protected virtual void ColorChanged()
    {
      OnBorderStateChanged();
    }

    #endregion

    #region events
    public event EventHandler BorderStateChanged
    {
      add
      {
        this.borderStateChanged += value;
      }

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

  }
}
