using System.Windows;
using System.Windows.Media;
using Microsoft.Research.DynamicDataDisplay.DataSources;
using Microsoft.Research.DynamicDataDisplay.PointMarkers;
using Microsoft.Research.DynamicDataDisplay.Common;

namespace Microsoft.Research.DynamicDataDisplay
{
  public class MarkersPointsGraph : PointsGraphBase
  {
    /// <summary>
    /// Initializes a new instance of the <see cref="MarkerPointsGraph"/> class.
    /// </summary>
    public MarkersPointsGraph()
    {
      ManualTranslate = true;
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="MarkerPointsGraph"/> class.
    /// </summary>
    /// <param name="dataSource">The data source.</param>
    public MarkersPointsGraph(IPointDataSource dataSource)
      : this()
    {
      DataSource = dataSource;
    }

    protected override void OnVisibleChanged(DataRect newRect, DataRect oldRect)
    {
      base.OnVisibleChanged(newRect, oldRect);
      InvalidateVisual();
    }

    public PointMarker[] Markers
    {
      get { return (PointMarker[])GetValue(MarkerProperty); }
      set { SetValue(MarkerProperty, value); }
    }

    public static readonly DependencyProperty MarkerProperty =
      DependencyProperty.Register(
        "Markers",
        typeof(PointMarker[]),
        typeof(MarkersPointsGraph),
        new FrameworkPropertyMetadata { DefaultValue = null, AffectsRender = true }
          );

    protected override void OnRenderCore(DrawingContext dc, RenderState state)
    {
      if (DataSource == null) return;
      if (Markers == null) return;

      var transform = Plotter2D.Viewport.Transform;

      DataRect bounds = DataRect.Empty;
      int index = 0;
      using (IPointEnumerator enumerator = DataSource.GetEnumerator(GetContext()))
      {
        Point point = new Point();
        while (enumerator.MoveNext())
        {
          enumerator.GetCurrent(ref point);
          PointMarker pointMarker = null;
          if (index >= Markers.Length) pointMarker=new CenteredTextMarker{Text=""};
          else pointMarker=Markers[index];
          enumerator.ApplyMappings(pointMarker);
          Point screenPoint = point.DataToScreen(transform);
          bounds = DataRect.Union(bounds, point);
          pointMarker.Render(dc, screenPoint);
          index++;
        }
      }

      Viewport2D.SetContentBounds(this, bounds);
    }
  }
}
