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

  [DataAxisGridDataCellDesignTimeVisibleAttribute(true)]
  public class DataAxisGridImageDataCell : DataAxisGridDataCellMan
  {
    #region privates
    private static readonly Type ImageType = typeof(System.Drawing.Image);
    private PictureSizeMode imageLayout = PictureSizeMode.Fit;
    private double scale = 1.0f;
    #endregion

    public DataAxisGridImageDataCell()
    {
    }

    #region properties
    [DefaultValue(PictureSizeMode.Fit)]
    public PictureSizeMode SizeMode
    {
      get { return imageLayout; }
      set
      {
        if (this.imageLayout != value)
        {
          imageLayout = value;
          Grid.InvalidateGrid();
        }
      }
    }

    [DefaultValue(1.0)]
    public double Scale
    {
      get
      {
        return scale;
      }

      set
      {
        if (scale != value)
        {
          scale = value;
          ScaleChanged();
        }
      }
    }

    #endregion

    private Image GetCellValueAsImage(PropertyAxisBar propAxisBar, object listItemBar)
    {
      object objValue;
      TypeConverter converter;

      if (propAxisBar != null && listItemBar != null)
      {
        objValue = propAxisBar.GetValue(listItemBar);
        if (objValue == null)
          return null;
        else if (objValue is Image)
          return (objValue as Image);
        else
        {
          converter = TypeDescriptor.GetConverter(ImageType);
          if (converter.CanConvertFrom(objValue.GetType()) == true)
            return (Image)converter.ConvertFrom(objValue);
          else
            return null;
        }
      }
      else
        return null;
    }

    protected override void PaintForeground(DataAxisGridDataCellPaintEventArgs e)
    {
      int nw, nh;
      double xyaspect;
      Image img = null;
      bool sizeFites;
      Rectangle imageDrawRect = Rectangle.Empty;

      if (e.PropAxisBar == null) return;

      Rectangle cellDrawRect = EhLibUtils.TrimPadding(e.CellRect, Padding);

      //ImageAttributes attr = new ImageAttributes();
      try
      {
        img = GetCellValueAsImage(e.PropAxisBar, e.ListItemBar);
      }
      catch (Exception expn)
      {
        if (EhLibUtils.IsCriticalException(expn))
        {
          throw;
        }
        else
        {
          string s = "Error: " + expn.Message;
          Rectangle textRect = EhLibUtils.TrimPadding(cellDrawRect, Padding);
          Grid.PaintingDrawText(e.Graphics, s, Font, textRect, ForeColor, HorizontalAlignment.Left, VerticalAlignment.Top, false);
        }
      }

      if (img == null) return;

      Size imageSize = img.Size;
      imageSize.Width = (int)Math.Round(imageSize.Width * Scale);
      imageSize.Height = (int)Math.Round(imageSize.Height * Scale);

      if (cellDrawRect.Width >= imageSize.Width &&
          cellDrawRect.Height >= imageSize.Height)
        sizeFites = true;
      else
        sizeFites = false;

      if (SizeMode == PictureSizeMode.Stretch)
      {
        imageDrawRect = cellDrawRect;
      }
      else if ((SizeMode == PictureSizeMode.Normal) ||
               (sizeFites && SizeMode == PictureSizeMode.Fit))
      {
        imageDrawRect.Width = imageSize.Width;
        imageDrawRect.Height = imageSize.Height;
        imageDrawRect.X = cellDrawRect.X + (cellDrawRect.Width - imageSize.Width) / 2;
        imageDrawRect.Y = cellDrawRect.Y + (cellDrawRect.Height - imageSize.Height) / 2;
      }
      else // (SizeMode == PictureSizeMode.Fit) || PictureSizeMode.Zoom
      {
        if ((imageSize.Width > 0) && (imageSize.Height > 0))
        {
          xyaspect = (double)imageSize.Width / imageSize.Height;
          nw = cellDrawRect.Width;
          nh = (int)(cellDrawRect.Width / xyaspect);
          if (nh > cellDrawRect.Height)
          {
            nh = cellDrawRect.Height;
            nw = (int)(cellDrawRect.Height * xyaspect);
          }
          imageDrawRect.Width = nw;
          imageDrawRect.Height = nh;
          imageDrawRect = EhLibUtils.RectCenter(imageDrawRect, cellDrawRect);
        }
      }

      Region oldClip = Grid.PaintingSetClip(e.Graphics, cellDrawRect, CombineMode.Intersect);
      e.Graphics.DrawImage(img, imageDrawRect, 0, 0, img.Width, img.Height, GraphicsUnit.Pixel);
      Grid.PaintingSetClip(e.Graphics, oldClip, CombineMode.Replace);
      //attr.Dispose();

    }

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

      if (!HeightOptions.AutoExpand)
        return base.CalcCellHeight(propAxisBar, listItemBar, cellWidth);

      Image img;

      try
      {
        img = GetCellValueAsImage(propAxisBar, listItemBar);
        if (img != null)
          th = (int)Math.Round(img.Height * Scale) + Padding.Top + Padding.Bottom;
      }
      catch (Exception expn)
      {
        if (EhLibUtils.IsCriticalException(expn))
        {
          throw;
        }
      }

      return th;
    }

    protected virtual void ScaleChanged()
    {
      if (Grid != null)
        Grid.RowHeightAffectPropertyChanged();
    }

    protected internal override void PrintCell(
      PrintServiceEventArgs e, Rectangle paintRect, int areaColIndex, int areaRowIndex, PrintServiceEventArgs printContext
        )
    {
      PropertyAxisBar propAxisBar;
      object listItemBar;

      AxisObjectsByDataColRowIndex(areaColIndex, areaRowIndex, out propAxisBar, out listItemBar);

      DataAxisGridDataCellPaintEventArgs paintEventArgs = new DataAxisGridDataCellPaintEventArgs(null, e.Graphics, -1, -1, 
        paintRect, 0, areaColIndex, areaRowIndex, new Point(-1, -1), propAxisBar, listItemBar);

      PaintForeground(paintEventArgs);
    }

  }

}
