@using Radzen.Blazor
@using Radzen.Blazor.Rendering
@typeparam TItem
@inherits Radzen.Blazor.CartesianSeries<TItem>
<CascadingValue Value="@this">
  @ChildContent
</CascadingValue>
@code {
  public override RenderFragment Render(ScaleBase categoryScale, ScaleBase valueScale)
  {
    var chart = RequireChart();
    var category = ComposeCategory(categoryScale);

    var value = ComposeValue(valueScale);

    var pathGenerator = GetPathGenerator();

    var data = Items.Select(item =>
    {
      var x = category(item);
      var y = value(item);

      return new Point<TItem> { X = x, Y = y, Data = item };
    });

    var ticks = chart.CategoryScale.Ticks(chart.CategoryAxis.TickDistance);
    var index = chart.Series.IndexOf(this);
    var className = $"rz-area-series rz-series-{index}";
    var gradientId = $"rzAreaGradient{chart.UniqueID}{index}";
    var gradientColor = Fill ?? "var(--rz-series-color)";

    return
    @<g class="@className">
      @if (Items.Any())
      {
        var x1 = category(Items.First()).ToInvariantString();
        var x2 = category(Items.Last()).ToInvariantString();
        var vs = chart.GetValueScale(ValueAxisName);
        var va = chart.GetValueAxis(ValueAxisName);
        var valueTicks = vs.Ticks(va.TickDistance);
        var start = Math.Max(0, valueTicks.Start);
        var y = vs.Scale(start).ToInvariantString();
        var style = $"clip-path: url(#{chart.ClipPath}); -webkit-clip-path: url(#{chart.ClipPath});";

        string area;
        string line;

        if (Interpolation == Interpolation.Step)
        {
            // For step interpolation, build path without the last vertical drop.
            // The StepGenerator's last V command creates a fold at the right edge
            // when the last value is higher than the previous, causing SVG's
            // nonzero winding rule to leave the transition area unfilled.
            var dataList = data.ToList();
            var stepPath = new System.Text.StringBuilder();

            stepPath.Append($"{dataList[0].X.ToInvariantString()} {dataList[0].Y.ToInvariantString()}");

            for (var i = 1; i < dataList.Count - 1; i++)
            {
                stepPath.Append($" H {dataList[i].X.ToInvariantString()} V {dataList[i].Y.ToInvariantString()}");
            }

            if (dataList.Count > 1)
            {
                stepPath.Append($" H {dataList[dataList.Count - 1].X.ToInvariantString()}");
            }

            var stepPathStr = stepPath.ToString();
            area = $"M {x1} {y} {stepPathStr} L {x2} {y}";
            line = $"M {stepPathStr}";
        }
        else
        {
            var path = pathGenerator.Path(data);
            area = $"M {x1} {y} {path} L {x2} {y}";
            line = $"M {path}";
        }

        @if (FillMode == FillMode.Gradient)
        {
            <defs>
                <linearGradient id="@gradientId" x1="0" y1="0" x2="0" y2="1">
                    <stop offset="0" style="@($"stop-color: {gradientColor}; stop-opacity: {GradientStartOpacity.ToInvariantString()}")"></stop>
                    <stop offset="1" style="@($"stop-color: {gradientColor}; stop-opacity: {GradientEndOpacity.ToInvariantString()}")"></stop>
                </linearGradient>
            </defs>
        }
        var animate = chart.AnimateDataUpdates;
        var lineKey = animate ? $"animated-line-{LineType}" : line;

        @if (FillMode != FillMode.None)
        {
            var fill = FillMode == FillMode.Gradient ? $"url(#{gradientId})" : Fill;
            var fillClass = FillMode == FillMode.Gradient ? "rz-area-gradient" : null;
            var fillKey = animate ? "animated-fill" : area;
            var fillStyle = animate ? $"d: path(\"{area}\");{style}" : style;
            <path @key="@fillKey" class="@($"{fillClass} {(animate ? "rz-path-transition" : null)}".Trim())" style="@fillStyle" d="@area" fill="@fill" stroke="none"></path>
        }
        <Path @key="@lineKey" D="@line" Stroke="@Stroke" StrokeWidth="@StrokeWidth" LineType="@LineType" Style="@style" Fill="none" Transition="@animate" />
      }
      <Markers Visible="@Markers.Visible" Series="@this" Data="@data" MarkerType="@MarkerType" Stroke="@Markers.Stroke" Fill="@(Markers.Fill ?? Stroke)" StrokeWidth="@Markers.StrokeWidth" Size="@Markers.Size" />
    </g>;
  }
}
