using UnityEngine;
using UnityEngine.UIElements;

public class DataFlowUnit : MonoBehaviour
{
    protected Transform _transform;
    protected Transform _rendererTransform;
    protected Transform _anchorPointTransform;

    //首尾位置
    [SerializeField] private float _startPointXPos;
    [SerializeField] private float _startPointYPos;
    [SerializeField] private float _endPointXPos;
    [SerializeField] private float _endPointYPos;
    //起始时间
    [SerializeField] private float _startTime;
    [SerializeField] private float _endTime;
    SongInformationContainer _songInformation;
    BPMGroup _BPMGroup;

    /// <summary>
    /// 现在时间与结束点时间的差值
    /// </summary>
    private float currentTimeInterval
    {
        get 
        {   
            if(_endTime - _songInformation.SongCurrentTime >= 0)
            {
                return _endTime - _songInformation.SongCurrentTime;
            }
            else return -(_endTime -_songInformation.SongCurrentTime);
        }
    }
    /// <summary>
    /// 开始时间与结束时间的差值
    /// </summary>
    private float timeInterval
    {
        get { return _endTime - _startTime; }
    }

    /// <summary>
    /// 使用相似三角形原理,对两点之间进行随时间的线性插值
    /// 
    /// </summary>
    public Vector3 _startPoint
    {
        get
        {
            //目前时间处于两点中间,
            if (_songInformation.SongCurrentTime < _endTime && _songInformation.SongCurrentTime >= _startTime)
            {
                return new(
                    _endPointXPos - currentTimeInterval * (_endPointXPos - _startPointXPos) / timeInterval,
                    _endPointYPos - currentTimeInterval * (_endPointYPos - _startPointYPos) / timeInterval,
                    0
                );
            }
            //最后应该与结束点重合
            if (_songInformation.SongCurrentTime >= _endTime)
            {
                return _endPoint;

            }
            //在开始时间还大于现在时间的情况下
            return new(
                    _startPointXPos,
                    _startPointYPos,
                    _BPMGroup.CurrentNoteSpeed * (_startTime - _songInformation.SongCurrentTime)
                );
        }
    }
    private Vector3 _endPoint
    {
        get
        {
            return new(
                    _endPointXPos,
                    _endPointYPos,
                    _BPMGroup.CurrentNoteSpeed * (_endTime - _songInformation.SongCurrentTime)
                );
        }
    }
    #region Mesh相关字段
    private MeshFilter _rendererMeshFilter;
    private int[] _triangles = new int[]
    {
        //front
        2,1,0,
        0,3,2,
        //left
        4,5,6,
        4,6,7,
        //back
        9,11,8,
        9,10,11,
        //right
        12,13,14,
        12,14,15,
        //up
        16,17,18,
        16,18,19,
        //buttom
        21,23,22,
        21,20,23,
    };
    private Vector2[] _uvs = new Vector2[]
    {
        // Front
        new Vector2(1.0f, 0.0f),
        new Vector2(1.0f, 1.0f),
        new Vector2(1.0f, 0.0f),
        new Vector2(0.0f, 0.0f),
        // Left
        new Vector2(1.0f, 1.0f),
        new Vector2(0.0f, 1.0f),
        new Vector2(0.0f, 0.0f),
        new Vector2(1.0f, 0.0f),
        // Back
        new Vector2(1.0f, 0.0f),
        new Vector2(1.0f, 1.0f),
        new Vector2(1.0f, 0.0f),
        new Vector2(0.0f, 0.0f),
        // Right
        new Vector2(1.0f, 1.0f),
        new Vector2(0.0f, 1.0f),
        new Vector2(0.0f, 0.0f),
        new Vector2(1.0f, 0.0f),
        //// Top
        new Vector2(0.0f, 0.0f),
        new Vector2(1.0f, 0.0f),
        new Vector2(1.0f, 1.0f),
        new Vector2(0.0f, 1.0f),
        // Bottom
        new Vector2(0.0f, 0.0f),
        new Vector2(1.0f, 0.0f),
        new Vector2(1.0f, 1.0f),
        new Vector2(0.0f, 1.0f),
    };
    private Vector3[] _vertex = new Vector3[24];
    private float _width = 0.4f;
    #endregion
    void Awake()
    {
        _transform = gameObject.GetComponent<Transform>();
        _rendererMeshFilter = _transform.Find("Renderer").GetComponent<MeshFilter>();
        _rendererTransform = _transform.Find("Renderer").GetComponent<Transform>();
        _anchorPointTransform = _transform.Find("HeadAnchorPoint").GetComponent<Transform>();
        //将mesh标记为动态
        _rendererMeshFilter.mesh.MarkDynamic();
    }

    void Update()
    {
        //渲染层的更新,包括Mesh以及判定点
        UpdateRenderer(_songInformation.SongCurrentTime);
        UpdateAnchorPoint(_songInformation.SongCurrentTime);

        if (Input.GetKeyDown(KeyCode.A)&& _songInformation.SongCurrentTime>=_startTime) 
        {
            Debug.Log(this.ToString());
        }
    }
    public override string ToString()
    {
        return 
            $"开始时间{_startTime}\n"+
            $"结束时间{_endTime}\n"+
            $"目前开始点的位置{_startPoint}\n" +
            $"目前结束点的位置{_endPoint}";
    }
    /// <summary>
    /// 用于更新渲染层
    /// </summary>
    void UpdateRenderer(float currentTime)
    {
        _rendererMeshFilter.mesh.Clear();
        _rendererMeshFilter.mesh = MeshEditor.DrawMeshByCoordinates(_rendererMeshFilter.mesh, _vertex, _triangles, _uvs, _startPoint, _endPoint, _width);

        //处于不生成生成范围时,调整为关闭状态并且返回
        if (currentTime > _endTime)
        {
            _rendererTransform.gameObject.SetActive(false);
            return;
        }

        _rendererTransform.gameObject.SetActive(true);
    }
    /// <summary>
    /// 更新头部定位点的位置
    /// </summary>
    void UpdateAnchorPoint(float currentTime)
    {
        _anchorPointTransform.position = new Vector3(_startPoint.x, _startPoint.y, 0);

        //处于不生成生成范围时,调整为关闭状态并且返回
        if (currentTime < _startTime - _BPMGroup.InitializeOffset || currentTime > _endTime)
        {
            _anchorPointTransform.gameObject.SetActive(false);
            return;
        }

        //发现自己已经开启时,返回
        if (_anchorPointTransform.gameObject.activeSelf == true)
        {
            return;
        }

        _anchorPointTransform.gameObject.SetActive(true);
    }
    public void Init(Vector2 startPoint, Vector2 endPoint, float startTime, float endTime, float width, SongInformationContainer container, BPMGroup timing)
    {
        //赋值坐标
        _startPointXPos = startPoint.x;
        _startPointYPos = startPoint.y;
        _endPointXPos = endPoint.x;
        _endPointYPos = endPoint.y;

        //给属性赋值
        _width = width;
        _songInformation = container;

        //获得时间
        _startTime = startTime;
        _endTime = endTime;

        _anchorPointTransform.gameObject.SetActive(false);
        _BPMGroup = timing;
    }

}
