using FishNet.Connection;
using FishNet.Object;
using FishNet.Object.Synchronizing;
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;

namespace _PROJECT.Multiplayer.NewBow
{
    public class TwoHandedBowNetworkManager : NetworkBehaviour
    {
        [SerializeField] private GameObject arrowPrefab;

        private XRInteractionManager _interactionManager;
        private TwoHandedBowNotch _notch;

        [SyncVar] private NetworkObject _arrowNetworkObject;
        public Vector3 lastKnownLaunchDirection { get; [ServerRpc(RunLocally = true)] set; }
        public float lastKnownPullAmount { get; [ServerRpc(RunLocally = true)] set; }


        public override void OnStartServer()
        {
            base.OnStartServer();
            _interactionManager = GameObject.Find("XR Interaction Manager").GetComponent<XRInteractionManager>();
            _notch = GetComponentInChildren<TwoHandedBowNotch>();
            
            if (_interactionManager == null)
                Debug.LogError("Interaction manager not found");
            if (_notch == null)
                Debug.LogError("Notch not found");
            
            CreateArrowServer();
        }

        public override void OnStartClient()
        {
            base.OnStartClient();
            _interactionManager = GameObject.Find("XR Interaction Manager").GetComponent<XRInteractionManager>();
            _notch = GetComponentInChildren<TwoHandedBowNotch>();
            
            if (_interactionManager == null)
                Debug.LogError("Interaction manager not found");
            if (_notch == null)
                Debug.LogError("Notch not found");
        }

        public void LaunchArrow(float pullAmount)
        {
            if (!IsOwner) return;
            lastKnownPullAmount = pullAmount;
            Debug.Log("Sending launch Arrow RPC");
            LaunchArrowRPC();
        }

        [ServerRpc(RequireOwnership = false)]
        private void LaunchArrowRPC()
        {
            if (!IsServer) return;
            Debug.Log("Got launch arrow RPC");
            if (_notch.hasSelection)
            {
                NetworkObject arrow = _notch.firstInteractableSelected.transform.GetComponent<NetworkObject>();
                OwnerDeselectRpc(Owner, arrow);
                _interactionManager.SelectExit(_notch, _notch.firstInteractableSelected);
                PlayReleaseSoundRPC();
            }

            _arrowNetworkObject = null;

            Invoke(nameof(CreateArrowServer), _notch.recycleDelayTime + 0.1f);
        }

        private void CreateArrowServer()
        {
            if (!IsServer) return;
            Debug.Log("Spawning arrow at " + transform.position);
            GameObject arrowObject = Instantiate(arrowPrefab, transform.position, transform.rotation);
            Spawn(arrowObject, Owner);
            Arrow arrow = arrowObject.GetComponent<Arrow>();
            _arrowNetworkObject = arrow.GetComponent<NetworkObject>();
            _interactionManager.SelectEnter(_notch as IXRSelectInteractor, arrow);
            OwnerSelectRpc(Owner, arrowObject.GetComponent<NetworkObject>());
            PlayNockSoundRPC();
        }
        
        public override void OnOwnershipClient(NetworkConnection prevOwner)
        {
            base.OnOwnershipClient(prevOwner);
            
            if (IsOwner && _arrowNetworkObject != null)
                TakeArrowOwnershipRPC();
        }
        
        [ServerRpc(RequireOwnership = false)]
        private void TakeArrowOwnershipRPC(NetworkConnection conn = null)
        {
            if (!IsServer) return;
            Debug.Assert(_arrowNetworkObject != null, "Network arrow was null, but bow should always have arrow");
            _arrowNetworkObject.GiveOwnership(conn);
            OwnerSelectRpc(conn, _arrowNetworkObject);
        }

        [TargetRpc]
        private void OwnerSelectRpc(NetworkConnection conn, NetworkObject arrow)
        {
            if (!IsClient) return;
            _interactionManager.SelectEnter(_notch as IXRSelectInteractor, arrow.gameObject.GetComponent<Arrow>());
        }

        [TargetRpc]
        private void OwnerDeselectRpc(NetworkConnection conn, NetworkObject arrow)
        {
            if (!IsClient) return;
            _interactionManager.SelectExit(_notch as IXRSelectInteractor, arrow.gameObject.GetComponent<Arrow>());
        }
        
        [ObserversRpc]
        private void PlayReleaseSoundRPC()
        {
            if (!IsClient) return;
            _notch.PlayReleaseSound();
        }
        
        [ObserversRpc]
        private void PlayNockSoundRPC()
        {
            if (!IsClient) return;
            _notch.PlayNockSound();
        }
        
        public void SetLaunchDirection(Vector3 direction)
        {
            if (!IsOwner) return;
            lastKnownLaunchDirection = direction;
        }
        
    }
}