using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace test1
{
    public class TableView1 : MonoBehaviour
    {
        
        private bool isScrolledToTop = false;
        private bool isScrolledToBottom = false;
        private ScrollRect scrollRect = null;
        public float threshold = 0.1f;
        private bool isInit = false;
        public int LineSize = 1;//每行个数
        public Vector2 spacing = new Vector2(0, 0);
        public GameObject perfabItem = null;//预制体
        public bool resetItemView = true;//如果 true宽度 / 行数 - 间距 > 单元格大小 缩放单元格; false 修改间距或行数 最大化匹配单元格大小
        private bool isHorizontal = false;

        private void Init()
        {
            if (isInit) return;
            scrollRect = GetComponent<ScrollRect>();
            isScrolledToTop = true;
            isScrolledToBottom = false;
            scrollRect.onValueChanged.AddListener(OnScroll);
            isHorizontal = scrollRect.horizontal;
            isInit = true;

        }


        private void OnScroll(Vector2 scrollPosition)
        {
            if (scrollPosition.y > threshold)
            {
                // 滑动距离超过阈值，表示不再触顶
                isScrolledToTop = false;
            }
            else if (scrollPosition.y < 1f - threshold)
            {
                // 滑动距离超过阈值，表示不再触底
                isScrolledToBottom = false;
            }

            // 判断是否触顶
            if (!isScrolledToTop && scrollPosition.y <= threshold)
            {
                isScrolledToTop = true;
                // 触顶事件处理
                Debug.Log("Scroll To Top");
            }

            // 判断是否触底
            if (!isScrolledToBottom && scrollPosition.y >= 1f - threshold)
            {
                isScrolledToBottom = true;
                // 触底事件处理
                Debug.Log("Scroll To Bottom");
            }
        }
        // Update is called once per frame
        void Update()
        {

        }
        private Vector2 getContentSize<T>(List<TableViewModel> data)
        {
            float width = 0;
            float height = 0;
            RectTransform rectTransform = GetComponent<RectTransform>();
            if (isHorizontal)
            {
                height = rectTransform.rect.height;
            }
            else
            {
                width = rectTransform.rect.width;
            }
            TableViewItem tableViewItem = perfabItem.GetComponent<T>() as TableViewItem;
            for (int i = 0; i < data.Count; i++)
            {
                Vector2 size = tableViewItem.getSize(0, data[0]);
                if (isHorizontal)
                {
                    width = width + size.x + spacing.x;
                }
                else
                {
                    height = height + size.y + spacing.y;
                }
            }
            if (data.Count > 0)
            {
                if (isHorizontal)
                {
                    width = width - spacing.x;
                }
                else
                {
                    height = height - spacing.y;
                }
            }
            if (isHorizontal)
            {
                width -= rectTransform.rect.width;
                if (width < rectTransform.rect.width) width = rectTransform.rect.width;
            }
            else
            {
                height -= rectTransform.rect.height;
                if (height < rectTransform.rect.height) height = rectTransform.rect.height;
            }
            return new Vector2(width, height);
        }
        private bool getItemView<T>(int idx, TableViewModel data, out T itemView)
        {
            string name = "tableView_auto_" + idx.ToString();
            var obj = transform.Find(name);
            if (obj == null)
            {
                GameObject item = Instantiate(perfabItem);
                item.name = name;
                itemView = item.GetComponent<T>();
                return false;
            }
            var temp = obj.GetComponent<T>() as TableViewItem;
            if (temp == null || temp.reuse(idx, data) == false)//已经无法复用重新生成
            {
                obj.SetParent(null);
                GameObject.Destroy(obj);
                GameObject item = Instantiate(perfabItem);
                item.name = name;
                itemView = item.GetComponent<T>();
                return false;
            }
            itemView = (T)temp;
            return true;
        }
        public void setData<T>(List<TableViewModel> data) where T : TableViewItem
        {
            //简单实现一个
            if (isInit == false) Init();
            if (perfabItem == null) return;
            Vector2 size = getContentSize<T>(data);
            var inRectTransform = scrollRect.content.GetComponent<RectTransform>();
            inRectTransform.sizeDelta = size;
            float width = size.x;
            float height = size.y;
            float start = 0;
            if (isHorizontal)
                start = 0;// - width/2;
            else
                start = 0;// - height / 2;
            Vector3 tempPos;
            Quaternion quaternion;
            for (int i = 0; i < data.Count; i++)
            {
                TableViewModel item = data[i];
                T itemView;
                TableViewItem tableViewItem = null;
                GameObject gameObjectItem = null;
                if (getItemView<T>(i, item, out itemView) == false)
                {
                    tableViewItem = (TableViewItem)itemView;
                    gameObjectItem = tableViewItem.getGameObject();
                    gameObjectItem.transform.SetParent(scrollRect.content);
                    tableViewItem.initViewData(item);
                }
                else
                {
                    tableViewItem = (TableViewItem)itemView;
                    gameObjectItem = tableViewItem.getGameObject();
                    tableViewItem.updateViewData(item);
                }
                var itemSize = tableViewItem.getSize(i, item);
                gameObjectItem.transform.GetLocalPositionAndRotation(out tempPos, out quaternion);
                if (isHorizontal)
                {
                    //gameObjectItem.transform.localPosition = new Vector3(start,0);
                    start = start + itemSize.x / 2;
                    tempPos.x = start;
                    tempPos.y = 0 - itemSize.y;
                    start = start + itemSize.x / 2 + spacing.x;
                }
                else
                {
                    start = start + itemSize.y / 2;
                    tempPos.y = start;
                    tempPos.x = itemSize.x / 2;
                    start = start + itemSize.y / 2 + spacing.y;
                }
                gameObjectItem.transform.SetLocalPositionAndRotation(tempPos, quaternion);
            }
        }

    }
}
public class TableView : MonoBehaviour
{
    private delegate void OnUpdateHandler();
    private OnUpdateHandler onUpdateHandler = null;
    private bool isScrolledToTop = false;
    private bool isScrolledToBottom = false;
    private ScrollRect scrollRect = null;
    public float threshold = 0.1f;
    private bool isInit = false;
    public int LineSize = 1;//每行个数
    public Vector2 spacing = new Vector2(0, 0);
    public bool reverse = false;
    public float head = 0;
    public float end = 0;
    public GameObject perfabItem = null;//预制体
    //public bool resetItemView = true;//如果 true宽度 / 行数 - 间距 > 单元格大小 缩放单元格; false 修改间距或行数 最大化匹配单元格大小
    public Vector2 cellSize = new Vector2(0,0);//如果未知指定就返回预制体的getSize 否则 
    private bool isHorizontal = false;
    RectTransform inRectTransform = null;
    private void Init()
    {
        if (isInit) return;
        scrollRect = GetComponent<ScrollRect>();
        isScrolledToTop = true;
        isScrolledToBottom = false;
        scrollRect.onValueChanged.AddListener(OnScroll);
        isHorizontal = scrollRect.horizontal;
        inRectTransform = scrollRect.content.GetComponent<RectTransform>();
        isInit = true;
    }


    private void OnScroll(Vector2 scrollPosition)
    {
        if (isInit == false) return;
        if (isHorizontal)
        {
            Debug.Log(scrollPosition.x * inRectTransform.rect.width);
        }
        else
        {
            Debug.Log(scrollPosition.y * inRectTransform.rect.height);
        }
        if(onUpdateHandler != null)
        {
            onUpdateHandler();
        }
        //if (scrollPosition.y > threshold)
        //{
        //    // 滑动距离超过阈值，表示不再触顶
        //    isScrolledToTop = false;
        //}
        //else if (scrollPosition.y < 1f - threshold)
        //{
        //    // 滑动距离超过阈值，表示不再触底
        //    isScrolledToBottom = false;
        //}

        //// 判断是否触顶
        //if (!isScrolledToTop && scrollPosition.y <= threshold)
        //{
        //    isScrolledToTop = true;
        //    // 触顶事件处理
        //    Debug.Log("Scroll To Top");
        //}

        //// 判断是否触底
        //if (!isScrolledToBottom && scrollPosition.y >= 1f - threshold)
        //{
        //    isScrolledToBottom = true;
        //    // 触底事件处理
        //    Debug.Log("Scroll To Bottom");
        //}
    }
    // Update is called once per frame
    void Update()
    {

    }
    private Vector2 getContentSize<T>(List<TableViewModel> data)
    {
        float width = 0;
        float height = 0;
        RectTransform rectTransform = GetComponent<RectTransform>();
        if (isHorizontal == false)
        {
            height = rectTransform.rect.height + cellSize.y * data.Count + head + end;
            width = rectTransform.rect.width;
        }
        else
        {
            width = rectTransform.rect.width + cellSize.x * data.Count + head + end;
            height = rectTransform.rect.height;
        }
        if(data.Count > 1)
        {
            if (isHorizontal)
            {
                width = width + (data.Count - 1) * spacing.x;
            }
            else {
                height = height + (data.Count - 1) * spacing.y;
            }
        }
        if (isHorizontal)
        {
            width = width - rectTransform.rect.width * 2;
            if (width < rectTransform.rect.width) width = rectTransform.rect.width;
        }
        else
        {
            height -= rectTransform.rect.height;
            if (height < rectTransform.rect.height) height = rectTransform.rect.height;
        }
        return new Vector2(width, height);
    }
    private bool getItemView<T>(int idx, TableViewModel data, out T itemView)
    {
        string name = "tableView_auto_" + idx.ToString();
        var obj = transform.Find(name);
        if (obj == null)
        {
            GameObject item = Instantiate(perfabItem);
            item.name = name;
            itemView = item.GetComponent<T>();
            return false;
        }
        var temp = obj.GetComponent<T>() as TableViewItem;
        if (temp == null || temp.reuse(idx, data) == false)//已经无法复用重新生成
        {
            obj.SetParent(null);
            GameObject.Destroy(obj);
            GameObject item = Instantiate(perfabItem);
            item.name = name;
            itemView = item.GetComponent<T>();
            return false;
        }
        itemView = (T)temp;
        return true;
    }
    bool isVisibleByPos(float x,float y)
    {
        return true;
    }
    public void setData<T>(List<TableViewModel> data) where T : TableViewItem
    {
        //简单实现一个
        if (isInit == false) Init();
        if (perfabItem == null) return;
        if (cellSize.x < 0.1 && cellSize.y < 0.1)
        {
            cellSize = ((TableViewItem)perfabItem.GetComponent<T>()).getSize(0,null);
        }
        Vector2 size = getContentSize<T>(data);
        inRectTransform.sizeDelta = size;
        onUpdateHandler = () =>
        {
            float width = size.x;
            float height = size.y;
            float start = head;
            Vector2 offsetSize = cellSize;
            Vector2 offsetSpacing = spacing;
            RectTransform rectTransform = GetComponent<RectTransform>();

            if (isHorizontal)
            {
                if (reverse == true)
                {
                    start = size.x + rectTransform.rect.width - end;
                    offsetSize.x = 0 - cellSize.x;
                    offsetSpacing.x = 0 - spacing.x;
                }
            }
            else
            {
                if (reverse == true)
                {
                    start = 0 - head;
                    offsetSize.y = 0 - cellSize.y;
                    offsetSpacing.y = 0 - spacing.y;
                }
                else
                {
                    start = 0 - size.y + end;
                }
            }
            Vector3 tempPos;
            Vector2 tempPos1;
            Quaternion quaternion;
            for (int i = 0; i < data.Count; i++)
            {
                TableViewModel item = data[i];
                T itemView;
                TableViewItem tableViewItem = null;
                GameObject gameObjectItem = null;
                if (isHorizontal)
                {
                    start = start + offsetSize.x / 2;
                    tempPos1.x = start;
                    tempPos1.y = 0 - size.y / 2;// - cellSize.y /2;
                }
                else
                {
                    start = start + offsetSize.y / 2;
                    tempPos1.y = start;
                    tempPos1.x = size.x / 2; ;
                }
                if (isVisibleByPos(tempPos1.x, tempPos1.y))
                {
                    if (getItemView<T>(i, item, out itemView) == false)
                    {
                        tableViewItem = itemView;
                        gameObjectItem = tableViewItem.getGameObject();
                        gameObjectItem.transform.SetParent(scrollRect.content);
                        tableViewItem.initViewData(item);
                    }
                    else
                    {
                        tableViewItem = itemView;
                        gameObjectItem = tableViewItem.getGameObject();
                        tableViewItem.updateViewData(item);
                    }
                    tableViewItem.debugTest(i % 3 == 2);
                    gameObjectItem.transform.GetLocalPositionAndRotation(out tempPos, out quaternion);
                    tempPos.x = tempPos1.x;
                    tempPos.y = tempPos1.y;
                    gameObjectItem.transform.SetLocalPositionAndRotation(tempPos, quaternion);
                }
                if (isHorizontal)
                {
                    start = start + offsetSize.x / 2 + offsetSpacing.x;
                }
                else
                {
                    start = start + offsetSize.y / 2 + offsetSpacing.y;
                }
            }
        };
        onUpdateHandler();
    }

}