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

using System;
using System.Drawing;
using System.Windows.Forms.VisualStyles;
using System.Windows.Forms;
using EhLib.Windows.Forms.VisualStyles;

namespace EhLib
{

  public enum DropDownButtonAlign
  {
    Right, Left, Neutral
  }

  public static class ComboBoxRenderer
  {

    [ThreadStatic]
    private static VisualStyleRenderer _visualStyleRenderer;

    private static readonly VisualStyleElement ComboBoxNeutralAlignElement = VisualStyleElement.ComboBox.DropDownButton.Normal;
    private static readonly VisualStyleElement TextBoxElement = VisualStyleElement.TextBox.TextEdit.Normal;
    private static readonly VisualStyleElement ComboBoxRightAlignElement = 
      VisualStyleElement.CreateElement("COMBOBOX", (int)COMBOBOXPARTS.CP_DROPDOWNBUTTONRIGHT, (int)DROPDOWNBUTTONRIGHTSTATES.CBXSR_NORMAL);
    private static readonly VisualStyleElement ComboBoxLeftAlignElement =
      VisualStyleElement.CreateElement("COMBOBOX", (int)COMBOBOXPARTS.CP_DROPDOWNBUTTONLEFT, (int)DROPDOWNBUTTONRIGHTSTATES.CBXSR_NORMAL);

    public static bool IsSupported
    {
      get
      {
        return VisualStyleRenderer.IsSupported;
      }
    }

    private static void DrawBackground(Graphics g, Rectangle bounds, ComboBoxState state)
    {
      _visualStyleRenderer.DrawBackground(g, bounds);
      //for disabled comboboxes, comctl does not use the window backcolor, so
      // we don't refill here in that case.
      if (state != ComboBoxState.Disabled)
      {
        Color windowColor = _visualStyleRenderer.GetColor(ColorProperty.FillColor);
        if (windowColor != SystemColors.Window)
        {
          Rectangle fillRect = _visualStyleRenderer.GetBackgroundContentRectangle(g, bounds);
          fillRect.Inflate(-2, -2);
          //then we need to re-fill the background.
          g.FillRectangle(SystemBrushes.Window, fillRect);
        }
      }
    }

    public static void DrawTextBox(Graphics g, Rectangle bounds, ComboBoxState state)
    {
      if (_visualStyleRenderer == null)
      {
        _visualStyleRenderer = new VisualStyleRenderer(TextBoxElement.ClassName, TextBoxElement.Part, (int)state);
      }
      else
      {
        _visualStyleRenderer.SetParameters(TextBoxElement.ClassName, TextBoxElement.Part, (int)state);
      }

      DrawBackground(g, bounds, state);
    }

    public static void DrawTextBox(Graphics g, Rectangle bounds, string comboBoxText, Font font, ComboBoxState state)
    {
      DrawTextBox(g, bounds, comboBoxText, font, TextFormatFlags.TextBoxControl, state);
    }

    public static void DrawTextBox(Graphics g, Rectangle bounds, string comboBoxText, Font font, Rectangle textBounds, ComboBoxState state)
    {
      DrawTextBox(g, bounds, comboBoxText, font, textBounds, TextFormatFlags.TextBoxControl, state);
    }

    public static void DrawTextBox(Graphics g, Rectangle bounds, string comboBoxText, Font font, TextFormatFlags formatFlags, ComboBoxState state)
    {
      if (_visualStyleRenderer == null)
      {
        _visualStyleRenderer = new VisualStyleRenderer(TextBoxElement.ClassName, TextBoxElement.Part, (int)state);
      }
      else
      {
        _visualStyleRenderer.SetParameters(TextBoxElement.ClassName, TextBoxElement.Part, (int)state);
      }

      Rectangle textBounds = _visualStyleRenderer.GetBackgroundContentRectangle(g, bounds);
      textBounds.Inflate(-2, -2);
      DrawTextBox(g, bounds, comboBoxText, font, textBounds, formatFlags, state);
    }

    public static void DrawTextBox(Graphics g, Rectangle bounds, string comboBoxText, Font font, Rectangle textBounds, TextFormatFlags flags, ComboBoxState state)
    {
      if (_visualStyleRenderer == null)
      {
        _visualStyleRenderer = new VisualStyleRenderer(TextBoxElement.ClassName, TextBoxElement.Part, (int)state);
      }
      else
      {
        _visualStyleRenderer.SetParameters(TextBoxElement.ClassName, TextBoxElement.Part, (int)state);
      }

      DrawBackground(g, bounds, state);
      Color textColor = _visualStyleRenderer.GetColor(ColorProperty.TextColor);
      TextRenderer.DrawText(g, comboBoxText, font, textBounds, textColor, flags);
    }

    public static ComboBoxState GetButtonState(bool isHot, bool isPressed, bool isDisabled)
    {
      if (isDisabled)
        return ComboBoxState.Disabled;
      else if (isPressed)
        return ComboBoxState.Pressed;
      else if (isHot)
        return ComboBoxState.Hot;
      else
        return ComboBoxState.Normal;
    }

    public static ButtonState ComboBoxStateToButtonState(ComboBoxState comboBoxState)
    {
      switch (comboBoxState)
      {
        case ComboBoxState.Normal: return ButtonState.Normal;
        case ComboBoxState.Hot: return ButtonState.Normal;
        case ComboBoxState.Pressed: return ButtonState.Pushed;
        case ComboBoxState.Disabled: return ButtonState.Inactive;
      }
      return ButtonState.Normal;
    }

    public static VisualStyleElement ComboBoxElement(DropDownButtonAlign align)
    {
      if (align == DropDownButtonAlign.Right)
        return ComboBoxRightAlignElement;
      else if (align == DropDownButtonAlign.Left)
        return ComboBoxLeftAlignElement;
      else
        return ComboBoxNeutralAlignElement;
    }

    public static void DrawDropDownButton(Graphics g, Rectangle bounds, ComboBoxState state, DropDownButtonAlign align, Control childControl) 
    {
      if (Application.RenderWithVisualStyles)
      { 
        if (_visualStyleRenderer == null)
        {
          _visualStyleRenderer = new VisualStyleRenderer(ComboBoxElement(align).ClassName, ComboBoxElement(align).Part, (int)state);
        }
        else
        {
          _visualStyleRenderer.SetParameters(ComboBoxElement(align).ClassName, ComboBoxElement(align).Part, (int)state);
        }

        if (_visualStyleRenderer.IsBackgroundPartiallyTransparent() && (childControl != null))
          _visualStyleRenderer.DrawParentBackground(g, bounds, childControl);
        _visualStyleRenderer.DrawBackground(g, bounds);
      }
      else
      {
        ControlPaint.DrawComboButton(g, bounds, ComboBoxStateToButtonState(state));
      }
    }

    public static bool DropDownButtonAlignSupported(DropDownButtonAlign align)
    {
      if (!Application.RenderWithVisualStyles)
      {
        if (align == DropDownButtonAlign.Neutral)
          return true;
        else
          return false;
      }
      else
      {
        if (align == DropDownButtonAlign.Right)
          return VisualStyleRenderer.IsElementDefined(ComboBoxRightAlignElement);
        else if (align == DropDownButtonAlign.Left)
          return VisualStyleRenderer.IsElementDefined(ComboBoxLeftAlignElement);
        else
          return true;
      }
    }
  }
}
