using System;
using System.Collections;
using System.Collections.Generic;
using System.Xml.Linq;
using Unity.VisualScripting;
using UnityEngine;
class IRunEventItem
{
    public MonoBehaviour monoBehaviour;
    public UInt64 randid;
    public void call(string eventName, List<UnityEngine.Object> uobjects,List<System.Object> objects)
    {
        (monoBehaviour as IEventHandler).onEventHandler(eventName, uobjects, objects);
    }
}

public class IRunEventManages
{
    private static Dictionary<string, List<UInt64>> eventPools = new Dictionary<string, List<ulong>>();
    private static Dictionary<UInt64, IRunEventItem> objs = new Dictionary<ulong, IRunEventItem>();
    public static bool isCheckCall = false;
    static IRunEventManages()
    {
    }
    public static bool ContainsName(MonoBehaviour monoBehaviour, string name)
    {
        if ((monoBehaviour is IEventHandler) == false)
        {
            return false;
        }

        if (eventPools.ContainsKey(name) == false)
        {
            return false;
        }
        foreach (var item in objs)
        {
            MonoBehaviour temp = item.Value.monoBehaviour;
            if (temp.Equals(monoBehaviour) && temp.gameObject.Equals(monoBehaviour.gameObject))
            {
                ulong runEventId = item.Value.randid;
                foreach (var item2 in eventPools[name])
                {
                    if (item2.Equals(runEventId)) return true;
                }
                return false;
            }
        }

        return false;
    }
    public static bool on(MonoBehaviour monoBehaviour,string name)
    {
        if((monoBehaviour is IEventHandler) == false)
        {
            return false;
        }
        IRunEventItem runEventItem = getRunItemByMonoBehaviour(monoBehaviour);
        if(runEventItem != null)
        {
            if (eventPools.ContainsKey(name) == false)
            {
                eventPools.Add(name, new List<UInt64>());
            }
            if (eventPools[name].IndexOf(runEventItem.randid) < 0)
            {
                eventPools[name].Add(runEventItem.randid);
            }
            return true;
        }
        UInt64 randid = newIRunEventId();
        runEventItem = new IRunEventItem();
        runEventItem.monoBehaviour = monoBehaviour;
        runEventItem.randid = randid;
        objs.Add(randid, runEventItem);
        if(eventPools.ContainsKey(name) == false)
        {
            eventPools.Add(name, new List<UInt64>());
        }
        eventPools[name].Add(randid);
        return true;
    }
    public static bool unOn(MonoBehaviour monoBehaviour,string name)
    {
        IRunEventItem runEvent = getRunItemByMonoBehaviour(monoBehaviour);
        if (runEvent == null) return false;
        UInt64 randid = runEvent.randid;
        if (name == null)
        {
            objs.Remove(randid);
            foreach (var item in eventPools)
            {
                if(item.Value.IndexOf(randid) >= 0)
                {
                    item.Value.Remove(randid);
                }
            }
            return true;
        }
        if(eventPools.ContainsKey(name) == false)
        {
            return false;
        }
        eventPools[name].Remove(runEvent.randid);
        return true;

    }
    public static bool send(string eventName, List<UnityEngine.Object> uobjects,List<System.Object> objects)
    {
        if (eventPools.ContainsKey(eventName) == false) return false;
        UInt64[] ulongs = new UInt64[eventPools[eventName].Count];
        eventPools[eventName].CopyTo(ulongs);
        foreach (var item in ulongs)
        {
            if (isCheckCall)
            {
                try
                {
                    objs[item].call(eventName, uobjects, objects);
                }
                catch (Exception e)
                {
                    Debug.Log(e);
                }
            }
            else
            {
                objs[item].call(eventName, uobjects, objects);
            }
        }
        return true;

    }
    private static IRunEventItem getRunItemByMonoBehaviour(MonoBehaviour monoBehaviour)
    {
        foreach (var item in objs)
        {
            MonoBehaviour temp = item.Value.monoBehaviour;
            if (temp.Equals(monoBehaviour) && temp.gameObject.Equals(monoBehaviour.gameObject))
            {
                return item.Value;
            }
        }
        return null;
    }
    private static UInt64 newIRunEventId()
    {
        while (true)
        {
            UInt64 randid = Convert.ToUInt64(UnityEngine.Random.value * 4155324154121022);
            if (objs.ContainsKey(randid) == false)
            {
                return randid;
            }
        }
    }
}
