using UniRx;
using UniRx.Triggers;
using UnityEngine;

public class BrotherPinkView : MonoBehaviour
{
    private static readonly int Normal = Animator.StringToHash("Normal");
    private static readonly int Promotion = Animator.StringToHash("Promotion");
    private static readonly int Sleepy = Animator.StringToHash("Sleepy");
    private static readonly int Walk = Animator.StringToHash("Walk");
    private static readonly Vector2 RightPos = new Vector2(4.96f, -0.26f);
    private static readonly Vector2 LeftPos = new Vector2(-4.96f, -0.26f);
    
    [SerializeField] private Animator animator;
    [SerializeField] private Transform pinkTransform;
    [SerializeField] private float walkSideBottomPos;
    [SerializeField] private float pinkWalkSpeed = 4f;
    [SerializeField] private float coolTime = 10f;
    [SerializeField] private int fewerBorder = 5;

    public int FewerBorder => fewerBorder;

    private bool isManyCustomer;
    private bool isLocked;
    private int nextId;
    private readonly (int trigger, Vector2 wayPoint, float wait)[] pinkMoves =
    {
        (Walk, LeftPos, 0f),
        (Promotion, LeftPos + Vector2.right * .03f, 5.35f),
        (Walk, RightPos, 0f),
        (Promotion, RightPos + Vector2.left * .03f, 5.35f),
    };
    private int moveIndex;
    private Vector2 wayPoint;
    private float durationDelta;
    private float completedDuration;
    private void Start()
    {
        nextId = Normal;
        isManyCustomer = true;
        this.UpdateAsObservable().Subscribe(_ =>
        {
            if (isManyCustomer || isLocked)
            {
                return;
            }
            var localPosition = pinkTransform.localPosition;
            localPosition = Vector2.MoveTowards(localPosition, wayPoint, pinkWalkSpeed * Time.deltaTime);
            localPosition = localPosition + Vector3.forward * (localPosition.y + Mathf.Abs(walkSideBottomPos));
            pinkTransform.localPosition = localPosition;
            if (Vector2.Distance(localPosition, wayPoint) < .01f)
            {
                if (durationDelta < completedDuration)
                {
                    durationDelta += Time.deltaTime;
                    return;
                }
                durationDelta = 0;
                moveIndex++;
                if (moveIndex == pinkMoves.Length)
                {
                    moveIndex = 0;
                    isLocked = true;
                    isManyCustomer = true;
                    animator.SetTrigger(nextId);
                    this.CallWaitForSeconds(coolTime, () =>
                    {
                        isLocked = false;
                    });
                    return;
                }
                SetPinkMove();
            }
        }).AddTo(this);
    }

    private void SetPinkMove()
    {
        var move = pinkMoves[moveIndex];
        wayPoint = move.wayPoint;
        completedDuration = move.wait;
        animator.SetTrigger(move.trigger);
        if (Vector2.Distance(wayPoint, pinkTransform.localPosition.ToVector2()) < .01f)
        {
            // nop
        } else if ((wayPoint - pinkTransform.localPosition.ToVector2()).x > 0)
        {
            pinkTransform.localRotation = Quaternion.Euler(Vector3.up * 180);
        }
        else
        {
            pinkTransform.localRotation = Quaternion.Euler(Vector3.zero);
        }
    }

    private void SetTrigger(int id)
    {
        if (nextId == id)
        {
            return;
        }
        nextId = id;
        if (isManyCustomer)
        {
            animator.SetTrigger(Normal);
        }
    }

    public void SetNormal()
    {
        SetTrigger(Normal);
    }

    public void SetSleepy()
    {
        SetTrigger(Sleepy);
    }
    
    public void SetPromotion()
    {
        isManyCustomer = true;
        pinkTransform.localPosition = LeftPos;
        animator.SetTrigger(Promotion);
    }
    
    public void SetWalk()
    {
        if (!isManyCustomer)
        {
            return;
        }
        if (!isLocked)
        {
            isManyCustomer = false;
            SetPinkMove();
        }
    }
}
