/************************************************/
/*                                              */
/*     Copyright (c) 2018 - 2021 monitor1394    */
/*     https://github.com/monitor1394           */
/*                                              */
/************************************************/

using UnityEngine;
using UnityEngine.UI;
using XUGL;

namespace XCharts
{
    public partial class CoordinateChart
    {
        protected void DrawCandlestickSerie(VertexHelper vh, int colorIndex, Serie serie)
        {
            if (!IsActive(serie.index)) return;
            if (serie.animation.HasFadeOut()) return;
            var showData = serie.GetDataList(dataZoom);
            var yAxis = m_YAxes[serie.yAxisIndex];
            var xAxis = m_XAxes[serie.xAxisIndex];
            var grid = GetSerieGridOrDefault(serie);
            float categoryWidth = AxisHelper.GetDataWidth(xAxis, grid.runtimeWidth, showData.Count, dataZoom);
            float barWidth = serie.GetBarWidth(categoryWidth);
            float space = (categoryWidth - barWidth) / 2;
            int maxCount = serie.maxShow > 0
                ? (serie.maxShow > showData.Count ? showData.Count : serie.maxShow)
                : showData.Count;

            bool dataChanging = false;
            float dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
            float yMinValue = yAxis.GetCurrMinValue(dataChangeDuration);
            float yMaxValue = yAxis.GetCurrMaxValue(dataChangeDuration);
            var isAllBarEnd = true;
            var isYAxis = false;
            for (int i = serie.minShow; i < maxCount; i++)
            {
                var serieData = showData[i];
                if (serie.IsIgnoreValue(serieData.GetData(1)))
                {
                    serie.dataPoints.Add(Vector3.zero);
                    continue;
                }
                var highlight = (tooltip.show && tooltip.IsSelected(i))
                    || serie.data[i].highlighted
                    || serie.highlighted;
                var itemStyle = SerieHelper.GetItemStyle(serie, serieData, highlight);
                var open = serieData.GetCurrData(0, dataChangeDuration, yAxis.inverse, yMinValue, yMaxValue);
                var close = serieData.GetCurrData(1, dataChangeDuration, yAxis.inverse, yMinValue, yMaxValue);
                var lowest = serieData.GetCurrData(2, dataChangeDuration, yAxis.inverse, yMinValue, yMaxValue);
                var heighest = serieData.GetCurrData(3, dataChangeDuration, yAxis.inverse, yMinValue, yMaxValue);
                var isRise = close > open;
                var borderWidth = open == 0 ? 0f
                    : (itemStyle.runtimeBorderWidth == 0 ? m_Theme.serie.candlestickBorderWidth
                    : itemStyle.runtimeBorderWidth);
                if (serieData.IsDataChanged()) dataChanging = true;
                float pX = grid.runtimeX + i * categoryWidth;
                float zeroY = grid.runtimeY + yAxis.runtimeZeroYOffset;
                if (!xAxis.boundaryGap) pX -= categoryWidth / 2;
                float pY = zeroY;
                var barHig = 0f;
                var valueTotal = yMaxValue - yMinValue;
                var minCut = (yMinValue > 0 ? yMinValue : 0);
                if (valueTotal != 0)
                {
                    barHig = (close - open) / valueTotal * grid.runtimeHeight;
                    pY += (open - minCut) / valueTotal * grid.runtimeHeight;
                }
                serieData.runtimeStackHig = barHig;
                var isBarEnd = false;
                float currHig = CheckAnimation(serie, i, barHig, out isBarEnd);
                if (!isBarEnd) isAllBarEnd = false;
                Vector3 plb, plt, prt, prb, top;

                plb = new Vector3(pX + space + borderWidth, pY + borderWidth);
                plt = new Vector3(pX + space + borderWidth, pY + currHig - borderWidth);
                prt = new Vector3(pX + space + barWidth - borderWidth, pY + currHig - borderWidth);
                prb = new Vector3(pX + space + barWidth - borderWidth, pY + borderWidth);
                top = new Vector3(pX + space + barWidth / 2, pY + currHig - borderWidth);
                if (serie.clip)
                {
                    plb = ClampInGrid(grid, plb);
                    plt = ClampInGrid(grid, plt);
                    prt = ClampInGrid(grid, prt);
                    prb = ClampInGrid(grid, prb);
                    top = ClampInGrid(grid, top);
                }
                serie.dataPoints.Add(top);
                var areaColor = isRise
                    ? itemStyle.GetColor(m_Theme.serie.candlestickColor)
                    : itemStyle.GetColor0(m_Theme.serie.candlestickColor0);
                var borderColor = isRise
                    ? itemStyle.GetBorderColor(m_Theme.serie.candlestickBorderColor)
                    : itemStyle.GetBorderColor0(m_Theme.serie.candlestickBorderColor0);
                var itemWidth = Mathf.Abs(prt.x - plb.x);
                var itemHeight = Mathf.Abs(plt.y - prb.y);
                var center = new Vector3((plb.x + prt.x) / 2, (plt.y + prb.y) / 2);
                var lowPos = new Vector3(center.x, zeroY + (lowest - minCut) / valueTotal * grid.runtimeHeight);
                var heighPos = new Vector3(center.x, zeroY + (heighest - minCut) / valueTotal * grid.runtimeHeight);
                var openCenterPos = new Vector3(center.x, prb.y);
                var closeCenterPos = new Vector3(center.x, prt.y);
                if (barWidth > 2f * borderWidth)
                {
                    if (itemWidth > 0 && itemHeight > 0)
                    {
                        if (ItemStyleHelper.IsNeedCorner(itemStyle))
                        {
                            UGL.DrawRoundRectangle(vh, center, itemWidth, itemHeight, areaColor, areaColor, 0,
                                itemStyle.cornerRadius, isYAxis, 0.5f);
                        }
                        else
                        {
                            CheckClipAndDrawPolygon(vh, ref prb, ref plb, ref plt, ref prt, areaColor, areaColor,
                                serie.clip, grid);
                        }
                        UGL.DrawBorder(vh, center, itemWidth, itemHeight, 2 * borderWidth, borderColor, 0,
                          itemStyle.cornerRadius, isYAxis, 0.5f);
                    }
                }
                else
                {
                    UGL.DrawLine(vh, openCenterPos, closeCenterPos, Mathf.Max(borderWidth, barWidth / 2), borderColor);
                }
                if (isRise)
                {
                    UGL.DrawLine(vh, openCenterPos, lowPos, borderWidth, borderColor);
                    UGL.DrawLine(vh, closeCenterPos, heighPos, borderWidth, borderColor);
                }
                else
                {
                    UGL.DrawLine(vh, closeCenterPos, lowPos, borderWidth, borderColor);
                    UGL.DrawLine(vh, openCenterPos, heighPos, borderWidth, borderColor);
                }
            }
            if (isAllBarEnd)
            {
                serie.animation.AllBarEnd();
            }
            if (dataChanging)
            {
                RefreshPainter(serie);
            }
        }
    }
}