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

public abstract class PageView : MonoBehaviour, IBeginDragHandler, IEndDragHandler
{
    public Action<int> OnPageChanged;

    protected Action OnScrollPage;
    protected Action OnReachEdge;

    public int CountPerPage;

    public float SlideSpeed = 4;  //滑动速度 
    public float sensitivity = 0.3f;

    [SerializeField] PageSpot mSpotView;
    [SerializeField] Transform mCtnPage;
    [SerializeField] GameObject mTplPage;
    [SerializeField] GameObject mTplCell;

    ScrollRect rect;      //滑动组件
    private float targethorizontal = 0;    //滑动的起始坐标 
    private bool isDrag = false;     //是否拖拽结束 
    List<float> posList = new List<float>();//求出每页的临界角，页索引从0开始 
    private int currentPageIndex = -1;

    private bool stopMove = true;
    private float startTime;

    private float startDragHorizontal;

    protected List<GameObject> mCellList;
    protected List<Transform> mPageList;

    #region page scroll
    void Awake()
    {
        rect = transform.GetComponent<ScrollRect>();
        AwakeInit();
    }

    void Update()
    {
        if (!isDrag && !stopMove)
        {
            startTime += Time.deltaTime;
            float t = startTime * SlideSpeed;
            rect.horizontalNormalizedPosition = Mathf.Lerp(rect.horizontalNormalizedPosition, targethorizontal, t);
            if (t >= 1)
            {
                stopMove = true;
                NotifyPageChange();
            }
        }
    }

    public void PageTo(int index, bool pWithScroll = true)
    {
        if (index >= 0 && index < posList.Count)
        {
            if (currentPageIndex != index)
            {
                currentPageIndex = index;

                if (pWithScroll)
                {
                    OnScrollPage?.Invoke();
                }
            }

            if (pWithScroll)
            {
                targethorizontal = posList[currentPageIndex]; //设置当前坐标，更新函数进行插值 
                isDrag = false;
                startTime = 0;
                stopMove = false;
            }
            else
            {
                rect.horizontalNormalizedPosition = posList[index];

                NotifyPageChange();
            }
        }
        else
        {
            //Debug.LogError("页码不存在");
        }
    }

    public void LastPage()
    {
        PageTo(currentPageIndex--);
    }

    public void NextPage()
    {
        PageTo(currentPageIndex++);
    }

    public void OnBeginDrag(PointerEventData eventData)
    {
        isDrag = true;
        startDragHorizontal = rect.horizontalNormalizedPosition;
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        float posX = rect.horizontalNormalizedPosition;
        posX += ((posX - startDragHorizontal) * sensitivity);
        float tTempPosX = posX;
        posX = posX < 1 ? posX : 1;
        posX = posX > 0 ? posX : 0;
        int index = 0;
        float offset = Mathf.Abs(posList[index] - posX);
        for (int i = 1; i < posList.Count; i++)
        {
            float temp = Mathf.Abs(posList[i] - posX);
            if (temp < offset)
            {
                index = i;
                offset = temp;
            }
        }
        PageTo(index);

        if (tTempPosX > 1 || tTempPosX < 0)
        {
            OnReachEdge?.Invoke();
        }
    }

    private void NotifyPageChange()
    {
        OnPageChanged?.Invoke(currentPageIndex);
        if (mSpotView != null)
        {
            mSpotView.SetPageIndex(currentPageIndex);
        }
    }
    #endregion

    #region config cell
    public abstract int Count
    {
        get;
    }

    public int PageCount => mPageCount;

    private int mPageCount;

    protected abstract void AwakeInit();
    protected abstract void BeforeLoad();

    protected abstract void ConfigCell(GameObject pCellGob, int pIndex);

    public void LoadData()
    {
        BeforeLoad();

        mPageCount = Count / CountPerPage + ((Count % CountPerPage) > 0 ? 1 : 0);

        int tSplitCount = Mathf.Max(1, mPageCount);
        float tDelta = tSplitCount > 1 ? (1f / (tSplitCount - 1)) : 1;

        for (int i = 0; i < tSplitCount; i++)
        {
            posList.Add(tDelta * i);
        }

        for (int i = 0; i < Count; i++)
        {
            GameObject tCell = GetCell(i);
            ConfigCell(tCell, i);
        }

        HideUnused();

        if (mSpotView != null)
        {
            mSpotView.Init(mPageCount);
        }

        PageTo(0, false);
    }

    private GameObject GetCell(int pCellIndex)
    {
        if (mCellList == null)
        {
            mCellList = new List<GameObject>();
        }

        GameObject tCell = null;
        if (pCellIndex < mCellList.Count)
        {
            tCell = mCellList[pCellIndex];
        }
        else
        {
            tCell = Instantiate(mTplCell, GetPage(pCellIndex));
            tCell.transform.localScale = Vector3.one;
            mCellList.Add(tCell);
        }

        tCell.SetActive(true);

        return tCell;
    }

    private Transform GetPage(int pCellIndex)
    {
        if (mPageList == null)
        {
            mPageList = new List<Transform>();
        }

        int tPageIndex = pCellIndex / CountPerPage;

        Transform tPage = null;
        if (tPageIndex < mPageList.Count)
        {
            tPage = mPageList[tPageIndex];
        }
        else
        {
            tPage = Instantiate(mTplPage, mCtnPage).transform;
            mPageList.Add(tPage);
        }

        tPage.gameObject.SetActive(true);

        return tPage;
    }

    private void HideUnused()
    {
        for (int i = Count; i < mCellList.Count; i++)
        {
            mCellList[i].SetActive(false);
        }

        for (int i = PageCount; i < mPageList.Count; i++)
        {
            mPageList[i].gameObject.SetActive(false);
        }
    }

    #endregion
}