@using Radzen.Blazor
@using Radzen.Blazor.Rendering
@typeparam TItem
@inherits Radzen.Blazor.CartesianSeries<TItem>
@implements IChartFullStackedColumnSeries

<CascadingValue Value="@this">
  @ChildContent
</CascadingValue>
@code {
    public override RenderFragment Render(ScaleBase categoryScale, ScaleBase valueScale)
    {
        var category = ComposeCategory(categoryScale);
        var style = Chart != null ? $"clip-path: url(#{Chart.ClipPath}); -webkit-clip-path: url(#{Chart.ClipPath});" : "";

        var columnIndex = ColumnIndex;
        var stackedColumnSeries = StackedColumnSeries;

        var width = ColumnWidth;
        var className = $"rz-full-stacked-column-series rz-series-{Chart?.Series?.IndexOf(this) ?? -1}";

        var groupStyle = $"--rz-zero-y: {valueScale.Scale(Math.Max(0, valueScale.Ticks(Chart?.ValueAxis?.TickDistance ?? 0).Start)).ToInvariantString()}px";
        var grad = new GradientFill(Chart?.UniqueID ?? "", Chart?.Series?.IndexOf(this) ?? -1);
        var gradient = FillMode == FillMode.Gradient;
        return
        @<g class="@className" style="@groupStyle">
            @foreach(var data in Items)
            {
                var x = GetColumnLeft(data, category);
                var y = GetColumnTop(data, columnIndex, category, stackedColumnSeries);
                var itemValue = Value(data);
                var radius = Chart?.ColumnOptions?.Radius ?? 0;
                var y0 = GetColumnBottom(data, columnIndex, category, stackedColumnSeries);

                if (itemValue < 0)
                {
                    (y, y0) = (y0, y);
                }

                if (radius > 0)
                {
                    var height = Math.Abs(y0 - y);

                    var items = stackedColumnSeries.SelectMany(series => series.ItemsForCategory(category(data))).OfType<TItem>()
                        .Where(item =>
                        {
                            var value = Value(item);
                            return itemValue >= 0 ? value >= 0 : value < 0;
                        }).ToList();

                    var index = items.IndexOf(data);

                    var nextValue = (index < items.Count - 1) ? Value(items[index + 1]) : 0;

                    if (radius > width / 2 || (index < items.Count - 1 && nextValue != 0) || radius > height)
                    {
                        radius = 0;
                    }
                }

                var path = $"M {x.ToInvariantString()} {(y+radius).ToInvariantString()} A {radius.ToInvariantString()} {radius.ToInvariantString()} 0 0 1 {(x + radius).ToInvariantString()} {y.ToInvariantString()} L {(x + width - radius).ToInvariantString()} {y.ToInvariantString()} A {radius.ToInvariantString()} {radius.ToInvariantString()} 0 0 1 {(x + width).ToInvariantString()} {(y+radius).ToInvariantString()} L {(x+width).ToInvariantString()} {y0.ToInvariantString()} L {x.ToInvariantString()} {y0.ToInvariantString()} Z";

                if (y > y0)
                {
                    path = $"M {x.ToInvariantString()} {y0.ToInvariantString()} L {(x+width).ToInvariantString()} {y0.ToInvariantString()} L {(x+width).ToInvariantString()} {(y-radius).ToInvariantString()} A {radius.ToInvariantString()} {radius.ToInvariantString()} 0 0 1 {(x + width - radius).ToInvariantString()} {y.ToInvariantString()} L {(x + radius).ToInvariantString()} {y.ToInvariantString()} A {radius.ToInvariantString()} {radius.ToInvariantString()} 0 0 1 {x.ToInvariantString()} {(y-radius).ToInvariantString()} L {x.ToInvariantString()} {y0.ToInvariantString()} Z";
                }
                var fill = PickColor(Items.IndexOf(data), Fills, Fill, FillRange, itemValue);
                var stroke = PickColor(Items.IndexOf(data), Strokes, Stroke, StrokeRange, itemValue);
                var fillRef = gradient ? grad.Url(fill ?? "var(--rz-series-color)", itemValue < 0 ? -1 : 1) : (FillMode == FillMode.None ? "none" : fill);

                <Path @key="@path" D="@path" Stroke="@stroke" StrokeWidth="@StrokeWidth" Fill="@fillRef" LineType="@LineType" Style="@style" />
            }
            @if (gradient)
            {
                <GradientDefs Plan="@grad" Vertical="true" StartOpacity="@GradientStartOpacity" EndOpacity="@GradientEndOpacity" />
            }
        </g>;
    }
}
