using System;
using System.Collections.Generic;
using RothenburgAR.Common;
using UnityEngine;


namespace RothenburgAR.UI
{
    internal class InputManager : Singleton<InputManager>
    {
        internal void Initialize()
        {
            Input.simulateMouseWithTouches = false;
        }

        private void Update()
        {
            HandleInputs();
        }

        private void HandleInputs()
        {
            List<Vector2> screenPoints = GatherScreenPoints();

            foreach (Vector2 screenPoint in screenPoints)
            {
                DoRaycast(screenPoint);
            }
        }

        public void DoRaycast(Vector2 screenPoint, bool denyBlockedHits = true)
        {
            RaycastHit hitInfo = new RaycastHit();
            Ray ray = Camera.main.ScreenPointToRay(screenPoint);
            Physics.Raycast(ray, out hitInfo);

            if (hitInfo.transform == null) return;

            GameObject go = hitInfo.transform.gameObject;
            var bb = go.GetComponent<PoiRaycastReceiverBehaviour>();
            if (bb == null) return;
            if (denyBlockedHits && DenyBlockedHits(screenPoint)) return;
            bb.OnClick.Invoke();
        }

        private bool DenyBlockedHits(Vector2 screenPoint)
        {
            if (!UIManager.Instance.IsARViewVisible) return true;

            var pointer = new UnityEngine.EventSystems.PointerEventData(UnityEngine.EventSystems.EventSystem.current);
            pointer.position = screenPoint;

            List<UnityEngine.EventSystems.RaycastResult> results = new List<UnityEngine.EventSystems.RaycastResult>();
            var _raycaster = UIManager.Instance.ARViewBehaviour.GetComponent<UnityEngine.UI.GraphicRaycaster>();
            _raycaster.Raycast(pointer, results);

            return results.Count != 0;
        }

        public void ActivateCrosshairs()
        {
            Vector2 center = new Vector2(Camera.main.pixelWidth / 2, Camera.main.pixelHeight / 2);
            DoRaycast(center, false);
        }

        private List<Vector2> GatherScreenPoints()
        {
            List<Vector2> screenPoint = new List<Vector2>();

            foreach (Touch t in Input.touches)
            {
                if (t.phase != TouchPhase.Began) continue;
                screenPoint.Add(t.position);
            }
            if (Input.GetMouseButtonDown(0))
            {
                screenPoint.Add(Input.mousePosition);
            }

            return screenPoint;
        }
    }
}