using System;
using UniRx;
using UniRx.Triggers;
using UnityEngine;

namespace MyGame.Scenes.MiniGame.Scripts
{
    public class Player : MonoBehaviour
    {
        [SerializeField] private float speed = 5f;
        [SerializeField] private float jumpTime = 1.25f;
        [SerializeField] private float jumpHeight = 5f;
        [SerializeField] private float hitTime = 1.5f;
        [SerializeField] private float hitWaitTime = 1f;
        private bool isJump;
        private bool isPreHit;
        private readonly BoolReactiveProperty isHit = new BoolReactiveProperty();
        private IDisposable hitDisposable;
        
        private void Start()
        {
            isHit.AddTo(this);
        }

        public void Move()
        {
            if (isHit.Value)
            {
                return;
            }
            transform.AddPositionX(speed * Time.deltaTime);
        }

        public void Jump()
        {
            if (isJump || isPreHit)
            {
                return;
            }

            isJump = true;
            var cachePos = transform.localPosition;
            this.CallLerp(jumpTime, t =>
            {
                transform.SetLocalPositionY(cachePos.y + Mathf.Sin(Mathf.PI * t) * jumpHeight);
            }, () =>
            {
                isJump = false;
            });
        }

        // こける
        public void Hit()
        {
            if (isPreHit)
            {
                return;
            }
            isPreHit = true;
            hitDisposable?.Dispose();
            // ジャンプが終わるのを待つ
            hitDisposable = this.UpdateAsObservable().First(_ => !isJump).Subscribe(_ =>
            {
                var orgRotation = transform.localRotation;
                var orgYAngle = orgRotation.eulerAngles.y;
                transform.rotation = Quaternion.identity;
                this.CallLerp(hitTime, t =>
                {
                    transform.localRotation = Quaternion.AngleAxis(orgYAngle + t * (3f * 360), Vector3.up);
                }, () =>
                {
                    isHit.Value = true;
                    this.CallWaitForSeconds(hitWaitTime, () =>
                    {
                        isPreHit = false;
                        isHit.Value = false;
                    });
                });
            }).AddTo(this);
        }
    }
}