using UnityEngine;
using System;
using System.Collections.Generic;
using mgaia.Utils;

public static class SubclassGetter
{
    public static IEnumerable<Type> GetDirectSubclasses<T>(bool concreteOnly)
    {
        return GetDirectSubclasses(typeof(T), concreteOnly);
    }

    public static IEnumerable<Type> GetDirectSubclasses(this Type parent, bool concreteOnly)
    {
        return GetSubclasses(parent, concreteOnly).Where(son => son.BaseType == parent);
    }

    public static IEnumerable<Type> GetSubclasses<T>(bool concreteOnly)
    {
        return GetSubclasses(typeof(T), concreteOnly);
    }

    public static IEnumerable<Type> GetSubclasses(this Type parent, bool concreteOnly)
    {
        Assert.AssertTrue(parent != null, "'parent' must be non-null");
        Assert.AssertTrue(WP8Extensions.IsClass(parent), "Type '" + parent.Name + "' is not a class type");

        return parent.Assembly
        .GetTypes()
            .Where(type => concreteOnly ? // Se for apenas concreta
                !(WP8Extensions.IsAbstract(type) || WP8Extensions.IsInterface(type)) && type.IsSubclassOf(parent) // não retorna abstratas e interfaces
                : type.IsSubclassOf(parent));
    }

    public static IEnumerable<Type> GetImplementing<T>(bool concreteOnly)
    {
        return GetImplementing(typeof(T), concreteOnly);
    }

    public static IEnumerable<Type> GetImplementing(this Type parentInterface, bool concreteOnly)
    {
        Assert.AssertTrue(parentInterface != null, "'parent' must be non-null");
        Assert.AssertTrue(WP8Extensions.IsInterface(parentInterface), "Type '" + parentInterface.Name + "' is not a interface type");

        return parentInterface.Assembly
        .GetTypes()
            .Where(type => concreteOnly ? // Se for apenas concreta
                !(WP8Extensions.IsAbstract(type) || WP8Extensions.IsInterface(type)) && type.GetInterfaces().Contains(parentInterface) // não retorna abstratas e interfaces
                : type.GetInterfaces().Contains(parentInterface));
    }	
}