using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

namespace XCharts.Runtime
{
    public static class LegendHelper
    {
        public static Color GetContentColor(BaseChart chart, int legendIndex, string legendName, Legend legend, ThemeStyle theme, bool active)
        {
            var textStyle = legend.labelStyle.textStyle;
            if (active)
            {
                if (legend.labelStyle.textStyle.autoColor)
                    return SeriesHelper.GetNameColor(chart, legendIndex, legendName);
                else
                    return !ChartHelper.IsClearColor(textStyle.color) ? textStyle.color : theme.legend.textColor;
            }
            else return theme.legend.unableColor;
        }

        public static Color GetIconColor(BaseChart chart, Legend legend, int readIndex, string legendName, bool active)
        {
            if (active)
            {
                if (legend.itemAutoColor)
                {
                    return SeriesHelper.GetNameColor(chart, readIndex, legendName);
                }
                else
                    return legend.GetColor(readIndex);
            }
            else return chart.theme.legend.unableColor;
        }

        public static LegendItem AddLegendItem(BaseChart chart, Legend legend, int i, string legendName, Transform parent,
            ThemeStyle theme, string content, Color itemColor, bool active, int legendIndex)
        {
            var objName = i + "_" + legendName;
            var anchorMin = new Vector2(0, 0.5f);
            var anchorMax = new Vector2(0, 0.5f);
            var pivot = new Vector2(0, 0.5f);
            var sizeDelta = new Vector2(100, 30);
            var iconSizeDelta = new Vector2(legend.itemWidth, legend.itemHeight);
            var textStyle = legend.labelStyle.textStyle;
            var contentColor = GetContentColor(chart, legendIndex, legendName, legend, theme, active);

            var objAnchorMin = new Vector2(0, 1);
            var objAnchorMax = new Vector2(0, 1);
            var objPivot = new Vector2(0, 1);
            var btnObj = ChartHelper.AddObject(objName, parent, objAnchorMin, objAnchorMax, objPivot, sizeDelta, i);
            var iconObj = ChartHelper.AddObject("icon", btnObj.transform, anchorMin, anchorMax, pivot, iconSizeDelta);
            var img = ChartHelper.GetOrAddComponent<Image>(btnObj);
            img.color = Color.clear;
            ChartHelper.GetOrAddComponent<Button>(btnObj);
            ChartHelper.GetOrAddComponent<Image>(iconObj);

            var label = ChartHelper.AddChartLabel("content", btnObj.transform, legend.labelStyle, theme.legend,
                content, contentColor, TextAnchor.MiddleLeft);
            label.SetActive(true);

            var item = new LegendItem();
            item.index = i;
            item.name = objName;
            item.legendName = legendName;
            item.SetObject(btnObj);
            item.SetIconSize(legend.itemWidth, legend.itemHeight);
            item.SetIconColor(itemColor);
            item.SetIconImage(legend.GetIcon(i));
            item.SetContentPosition(legend.labelStyle.offset);
            item.SetContent(content);
            return item;
        }

        public static void ResetItemPosition(Legend legend, Vector3 chartPos, float chartWidth, float chartHeight)
        {
            legend.location.UpdateRuntimeData(chartWidth, chartHeight);
            var startX = 0f;
            var startY = 0f;
            var legendMaxWidth = chartWidth - legend.location.runtimeLeft - legend.location.runtimeRight;
            var legendMaxHeight = chartHeight - legend.location.runtimeTop - legend.location.runtimeBottom;
            UpdateLegendWidthAndHeight(legend, legendMaxWidth, legendMaxHeight);
            var legendRuntimeWidth = legend.context.width;
            var legendRuntimeHeight = legend.context.height;
            var isVertical = legend.orient == Orient.Vertical;
            switch (legend.location.align)
            {
                case Location.Align.TopCenter:
                    startX = chartPos.x + chartWidth / 2 - legendRuntimeWidth / 2;
                    startY = chartPos.y + chartHeight - legend.location.runtimeTop;
                    break;
                case Location.Align.TopLeft:
                    startX = chartPos.x + legend.location.runtimeLeft;
                    startY = chartPos.y + chartHeight - legend.location.runtimeTop;
                    break;
                case Location.Align.TopRight:
                    startX = chartPos.x + chartWidth - legendRuntimeWidth - legend.location.runtimeRight;
                    startY = chartPos.y + chartHeight - legend.location.runtimeTop;
                    break;
                case Location.Align.Center:
                    startX = chartPos.x + chartWidth / 2 - legendRuntimeWidth / 2;
                    startY = chartPos.y + chartHeight / 2 + legendRuntimeHeight / 2;
                    break;
                case Location.Align.CenterLeft:
                    startX = chartPos.x + legend.location.runtimeLeft;
                    startY = chartPos.y + chartHeight / 2 + legendRuntimeHeight / 2;
                    break;
                case Location.Align.CenterRight:
                    startX = chartPos.x + chartWidth - legendRuntimeWidth - legend.location.runtimeRight;
                    startY = chartPos.y + chartHeight / 2 + legendRuntimeHeight / 2;
                    break;
                case Location.Align.BottomCenter:
                    startX = chartPos.x + chartWidth / 2 - legendRuntimeWidth / 2;
                    startY = chartPos.y + legendRuntimeHeight + legend.location.runtimeBottom;
                    break;
                case Location.Align.BottomLeft:
                    startX = chartPos.x + legend.location.runtimeLeft;
                    startY = chartPos.y + legendRuntimeHeight + legend.location.runtimeBottom;
                    break;
                case Location.Align.BottomRight:
                    startX = chartPos.x + chartWidth - legendRuntimeWidth - legend.location.runtimeRight;
                    startY = chartPos.y + legendRuntimeHeight + legend.location.runtimeBottom;
                    break;
            }
            if (isVertical) SetVerticalItemPosition(legend, legendMaxHeight, startX, startY);
            else SetHorizonalItemPosition(legend, legendMaxWidth, startX, startY);
        }

        private static void SetVerticalItemPosition(Legend legend, float legendMaxHeight, float startX, float startY)
        {
            var currHeight = 0f;
            var offsetX = 0f;
            var row = 0;
            foreach (var kv in legend.context.buttonList)
            {
                var item = kv.Value;
                if (currHeight + item.height > legendMaxHeight)
                {
                    currHeight = 0;
                    offsetX += legend.context.eachWidthDict[row];
                    row++;
                }
                item.SetPosition(new Vector3(startX + offsetX, startY - currHeight));
                currHeight += item.height + legend.itemGap;
            }
        }
        private static void SetHorizonalItemPosition(Legend legend, float legendMaxWidth, float startX, float startY)
        {
            var currWidth = 0f;
            var offsetY = 0f;
            foreach (var kv in legend.context.buttonList)
            {
                var item = kv.Value;
                if (currWidth + item.width > legendMaxWidth)
                {
                    currWidth = 0;
                    offsetY += legend.context.eachHeight;
                }
                item.SetPosition(new Vector3(startX + currWidth, startY - offsetY));
                currWidth += item.width + legend.itemGap;
            }
        }

        private static void UpdateLegendWidthAndHeight(Legend legend, float maxWidth, float maxHeight)
        {
            var width = 0f;
            var height = 0f;
            var realHeight = 0f;
            var realWidth = 0f;
            legend.context.eachWidthDict.Clear();
            legend.context.eachHeight = 0;
            if (legend.orient == Orient.Horizonal)
            {
                foreach (var kv in legend.context.buttonList)
                {
                    if (width + kv.Value.width > maxWidth)
                    {
                        realWidth = width - legend.itemGap;
                        realHeight += height + legend.itemGap;
                        if (legend.context.eachHeight < height + legend.itemGap)
                        {
                            legend.context.eachHeight = height + legend.itemGap;
                        }
                        height = 0;
                        width = 0;
                    }
                    width += kv.Value.width + legend.itemGap;
                    if (kv.Value.height > height)
                        height = kv.Value.height;
                }
                width -= legend.itemGap;
                legend.context.height = realHeight + height;
                legend.context.width = realWidth > 0 ? realWidth : width;
            }
            else
            {
                var row = 0;
                foreach (var kv in legend.context.buttonList)
                {
                    if (height + kv.Value.height > maxHeight)
                    {
                        realHeight = height - legend.itemGap;
                        realWidth += width + legend.itemGap;
                        legend.context.eachWidthDict[row] = width + legend.itemGap;
                        row++;
                        height = 0;
                        width = 0;
                    }
                    height += kv.Value.height + legend.itemGap;
                    if (kv.Value.width > width)
                        width = kv.Value.width;
                }
                height -= legend.itemGap;
                legend.context.height = realHeight > 0 ? realHeight : height;
                legend.context.width = realWidth + width;
            }
        }

        private static bool IsBeyondWidth(Legend legend, float maxWidth)
        {
            var totalWidth = 0f;
            foreach (var kv in legend.context.buttonList)
            {
                var item = kv.Value;
                totalWidth += item.width + legend.itemGap;
                if (totalWidth > maxWidth) return true;
            }
            return false;
        }

        public static bool CheckDataShow(Serie serie, string legendName, bool show)
        {
            bool needShow = false;
            if (legendName.Equals(serie.serieName))
            {
                serie.show = show;
                serie.highlight = false;
                if (serie.show) needShow = true;
            }
            else
            {
                foreach (var data in serie.data)
                {
                    if (legendName.Equals(data.name))
                    {
                        data.show = show;
                        data.context.highlight = false;
                        if (data.show) needShow = true;
                    }
                }
            }
            return needShow;
        }

        public static bool CheckDataHighlighted(Serie serie, string legendName, bool heighlight)
        {
            bool show = false;
            if (legendName.Equals(serie.serieName))
            {
                serie.highlight = heighlight;
            }
            else
            {
                foreach (var data in serie.data)
                {
                    if (legendName.Equals(data.name))
                    {
                        data.context.highlight = heighlight;
                        if (data.context.highlight) show = true;
                    }
                }
            }
            return show;
        }
    }
}