using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;

public class TextAnimation : MonoBehaviour
{
    [SerializeField] TMP_Text m_text;
    Mesh m_mesh;
    Vector3[] m_verts;

    [SerializeField] float m_scalar = 20;
    [SerializeField] float m_timeOffset = 0.1f;
    [SerializeField] float m_speed = 1;

    public enum AnimationType
    {
        None = 0,
        Wave_Char,
        Wave_Vert,
        Rotate_Char,
    }

    [SerializeField] AnimationType m_aniType;

    private void Start()
    {

    }

    private void LateUpdate()
    {
        if (m_text != null && m_text.enabled)
        {
            m_text.ForceMeshUpdate();
            m_mesh = m_text.mesh;
            m_verts = m_mesh.vertices;

            Effect();
            //CharacterWave();
            //VertexWave();
            //CharacterRotate();

            m_mesh.vertices = m_verts;
            m_text.canvasRenderer.SetMesh(m_mesh);
        }

    }

    protected virtual void Effect()
    {
        //nothing, to be overriden
        switch (m_aniType)
        {
            case AnimationType.Wave_Char:
                CharacterWave();
                break;
            case AnimationType.Wave_Vert:
                VertexWave();
                break;
            case AnimationType.Rotate_Char:
                CharacterRotate();
                break;
            default:
                //nothing.
                break;
        }
    }

    protected void VertexWave()
    {
        for (int i = 0; i < m_verts.Length; i++)
        {
            m_verts[i] += Vector3.up * Mathf.Sin(Time.time * m_speed + i * m_timeOffset) * m_scalar;
        }
    }
    protected void CharacterWave()
    {
        Debug.Log("CC: " + m_verts[0].y);
        for (int i = 0; i < m_text.textInfo.characterCount; i++)
        {
            if (m_text.text[i] == ' ')
                continue;

            TMP_CharacterInfo chInfo = m_text.textInfo.characterInfo[i];

            int index = chInfo.vertexIndex;
            Vector3 offset = Vector3.up * Mathf.Sin(Time.time * m_speed + i * m_timeOffset) * m_scalar;

            m_verts[index] += offset;
            m_verts[index + 1] += offset;
            m_verts[index + 2] += offset;
            m_verts[index + 3] += offset;

        }
    }

    protected void CharacterRotate()
    {
        int charCount = Mathf.Min(m_text.maxVisibleCharacters, m_text.textInfo.characterCount);

        for (int i = 0; i < charCount; i++)
        {
            //Debug.Log($"'{m_text.text[i]}'");
            if (m_text.text[i] == ' ')
                continue;

            TMP_CharacterInfo chInfo = m_text.textInfo.characterInfo[i];

            int index = chInfo.vertexIndex;

            float angle = Mathf.Sin(Time.time * m_speed + i * m_timeOffset) * m_scalar;
            Vector3 centre = (m_verts[index] + m_verts[index + 1] + m_verts[index + 2] + m_verts[index + 3]) * .25f;
            Quaternion angleAxis = Quaternion.AngleAxis(angle, Vector3.forward);
            m_verts[index] = RotateAroundPoint(centre, m_verts[index], angleAxis);
            m_verts[index + 1] = RotateAroundPoint(centre, m_verts[index + 1], angleAxis);
            m_verts[index + 2] = RotateAroundPoint(centre, m_verts[index + 2], angleAxis);
            m_verts[index + 3] = RotateAroundPoint(centre, m_verts[index + 3], angleAxis);
        }
    }

    public static Vector3 RotateAroundPoint(Vector3 _point, Vector3 _toRot, Quaternion _angleAxis)
    {
        return _angleAxis * (_toRot - _point) + _point;
    }


    public void SetAnimation(AnimationType _type)
    {
        m_aniType = _type;
    }
}