﻿using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;

namespace AsmodeeDigital.PlayReal.Samples.UI
{
    [RequireComponent(typeof(RectTransform))]
    public class Draggable : MonoBehaviour, IPointerDownHandler
    {
        public Draggable ItemToCreate;
        [HideInInspector]
        public RectTransform RectTransform;
        [HideInInspector]
        public DropSlot DropSlot;
        [HideInInspector]
        public System.Object Data;

        public UnityEventDraggable OnDraggableCreated;

        private bool _isDragged = false;
        private bool _createNewDraggable = true;

        private void Start()
        {
            RectTransform = this.GetComponent<RectTransform>();
        }

        private void Update()
        {
            if (_isDragged)
            {
                Vector3 mouseToScreen = Camera.main.ScreenToWorldPoint(Input.mousePosition);
                this.transform.position = new Vector3(mouseToScreen.x, mouseToScreen.y);

                if (Input.GetMouseButtonUp(0))
                {
                    PointerEventData pointerEventData = new UnityEngine.EventSystems.PointerEventData(EventSystem.current);
                    pointerEventData.position = Input.mousePosition;
                    pointerEventData.pointerDrag = this.gameObject;

                    GraphicRaycaster g = GameObject.FindObjectOfType<GraphicRaycaster>();
                    List<RaycastResult> result = new List<RaycastResult>();

                    g.Raycast(pointerEventData, result);

                    RaycastResult rrDropSlot = result.Find(rr => rr.gameObject.GetComponent<DropSlot>());
                    if (rrDropSlot.gameObject != null)
                    {
                        DropSlot dropSlot = rrDropSlot.gameObject.GetComponent<DropSlot>();
                        dropSlot.OnDrop(pointerEventData);
                    }

                    OnEndDrag();
                }
            }
        }

        public void OnEndDrag()
        {
            if (transform.parent.GetComponent<DropSlot>() == null)
            {
                if (this.DropSlot != null)
                    this.DropSlot.OnDraggableDeleted.Invoke();

                Destroy(this.gameObject);
            }
            else
            {
                _isDragged = false;
            }
        }

        public void OnPointerDown(PointerEventData eventData)
        {
            Canvas canvas = GameObject.FindObjectOfType<Canvas>();

            if (_createNewDraggable)
            {
                Draggable draggable = Instantiate<Draggable>(ItemToCreate ?? this);
                draggable._isDragged = true;
                draggable.transform.SetParent(canvas.transform);
                draggable.transform.position = this.transform.position;
                draggable.transform.localScale = Vector3.one;
                draggable.RectTransform.SetAsLastSibling();
                draggable._createNewDraggable = false;

                OnDraggableCreated.Invoke(this, draggable);
            }
            else
            {
                _isDragged = true;
                this.transform.SetParent(canvas.transform);
                this.RectTransform.SetAsLastSibling();
            }
        }
    }

    [Serializable]
    public class UnityEventDraggable : UnityEvent<Draggable, Draggable>
    {
    }
}
