using UnityEngine;
using System.Collections;
using System.Linq;
using System.Collections.Generic;
using System;
using UniRx;

public static class UnityEngineExtensions
{
    public static TimeSpan ToSec(this float seconds) => TimeSpan.FromSeconds(seconds);


    public static T AddOrGetComponent<T>(this GameObject gameObject) where T : Component
    {
        var component = gameObject.GetComponent<T>();
        if (component == null)
            return gameObject.AddComponent<T>();
        return component;
    }
    public static T AddOrGetComponent<T>(this Component component) where T : Component
    {
        return AddOrGetComponent<T>(component.gameObject);
    }

    public static T FindObjectWithInterface<T>(this GameObject inObj) where T : class
    {
        return inObj.GetComponents<Component>().OfType<T>().FirstOrDefault();
    }
    public static T GetInterface<T>(this GameObject inObj) where T : class
    {
        return inObj.GetComponents<Component>().OfType<T>().FirstOrDefault();
    }

    public static T GetInterface<T>(this Component inObj) where T : class
    {
        return inObj.GetComponents<Component>().OfType<T>().FirstOrDefault();
    }
    public static bool HasInterface<T>(this GameObject inObj) where T : class
    {
        return inObj.GetComponents<Component>().OfType<T>().FirstOrDefault() != null;
    }

    public static bool HasInterface<T>(this Component inObj) where T : class
    {
        return inObj.GetComponents<Component>().OfType<T>().FirstOrDefault() != null;
    }
    public static bool HasComponent<T>(this GameObject inObj) where T : Component
    {
        return inObj.GetComponent<T>() != null;
    }
    public static bool HasComponent<T>(this Component inObj) where T : Component
    {
        return inObj.GetComponent<T>() != null;
    }
    public static bool IsNearTo(this float first, float second, float margin)
    {
        return first - second <= margin || second - first <= margin;
    }/// <summary>
     /// Find all prefabs containing a specific component (T)
     /// </summary>
     /// <typeparam name="T">The type of component</typeparam>
    public static List<GameObject> LoadPrefabsContaining<T>(string path) where T : UnityEngine.Component
    {
        List<GameObject> result = new List<GameObject>();

        var allFiles = Resources.LoadAll<UnityEngine.Object>(path);
        foreach (var obj in allFiles)
        {
            if (obj is GameObject)
            {
                GameObject go = obj as GameObject;
                if (go.GetComponent<T>() != null)
                {
                    result.Add(go);
                }
            }
        }
        return result;
    }

    public static IEnumerable<Type> GetTypesImplementingInterface<T>()
    {
        var type = typeof(T);
        if (type.IsInterface)
        {
            var z = AppDomain.CurrentDomain.GetAssemblies();
            return z.SelectMany(s => s.GetTypes())
                         .Where(p => type.IsAssignableFrom(p));
        }
        //   Debug.LogError(typeof(T) + "Is not interface");
        return Array.Empty<Type>();

    }
    public static IEnumerable<Type> GetUnityObjectsImplementingInterface<T>()
    {
        var z = GetTypesImplementingInterface<T>().ToList();
        return z.Where(p => typeof(UnityEngine.Object).IsAssignableFrom(p));

    }

}
public class ReactiveCamera : ReactiveProperty<Camera> { }
