using System;
using System.Collections;
using Cinemachine;
using DG.Tweening;
using Google.Apis.Util;
using UnityEngine;
using UnityEngine.Diagnostics;
using UnityEngine.Events;
using UnityEngine.InputSystem;

public class BazFinalSequence : MonoBehaviour
{
    [Serializable]
    private struct Baz
    {
        public Door door;
        public Animator anim;
        public float pauseTime;
        public float scaleFactor;
        
        public GameObject graphics;
        public Transform scaleTarget;
        public float hoverHeight;
    }

    [Serializable]
    private struct Flickers
    {
        public float intensity;
        public float period;
    }
    
    [SerializeField] private GameObject _player;
    [SerializeField] private CinemachineFreeLook _camera;
    [SerializeField] private Baz _baz;
    [SerializeField] private GameObject _statue;
    [SerializeField] private Flickers _flickers;

    [SerializeField]
    private BoxCollider _endDialogue;
    
    private WaitForSeconds _bazPauseForEffect;
    private WaitForSeconds _bazWalk;

    private bool _finished = false;

    [SerializeField]
    private UnityEvent _finishEvent;
    [SerializeField]
    private BoxCollider _finishDialogue;

    private void Awake()
    {
        _bazPauseForEffect = new WaitForSeconds(_baz.pauseTime);
        _bazWalk = new WaitForSeconds(_baz.door.AnimTime);
    }

    public void Trigger()
    {
        StartCoroutine(BazCR());
    }

    public void FinishOff()
    {
        _finished = true;
    }

    public void CrashGame()
    {
        Utils.ForceCrash( ForcedCrashCategory.AccessViolation );
    }
    
    private IEnumerator BazCR()
    {
        // TODO: disable player movement/abilities
        var input = _player.GetComponent<PlayerInput>();
        input.enabled = false;

        // _camera.LookAt = _baz.scaleTarget;
        // _camera.Follow = _baz.scaleTarget;
        
        var elapsed = 0f;
        while (elapsed < _flickers.period)
        {
            elapsed += Time.deltaTime;
            
            var t = Time.time * _flickers.intensity;
            var p = Mathf.PerlinNoise(t, Mathf.Sin(t));

            _statue.SetActive(p > elapsed/_flickers.period);
            _baz.graphics.SetActive(!_statue.activeSelf);
            
            yield return null;
        }
        
        // there is no xandar only baz
        _statue.SetActive(false);
        _baz.graphics.SetActive(true);
        
        // wait a couple of moments
        yield return _bazPauseForEffect;

        // baz float-walks to the player
        _baz.door.Open();
        _baz.anim.SetBool("moving", true);

        var ogScale = _baz.scaleTarget.localScale;
        _baz.scaleTarget.DOScale(ogScale * _baz.scaleFactor, _baz.door.AnimTime);
        
        yield return _bazWalk;

        _baz.anim.SetBool("moving", false);

        var pos = _baz.scaleTarget.position;
        var playerPos = _player.transform.position;
        pos.y = playerPos.y + _baz.hoverHeight;
        _baz.scaleTarget.position = pos;
        _baz.scaleTarget.LookAt(playerPos + _baz.hoverHeight * Vector3.up);

        // roll credits!
        
        yield return new WaitForSecondsRealtime( 1f );
        _endDialogue.enabled = true;

        while ( !_finished )
        {
            yield return null;
        }
        
        _finishEvent.Invoke();
        
        yield return new WaitForSecondsRealtime( 1f );

        _finishDialogue.enabled = true;
    }
}
