using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;

namespace Tools
{
    public static class Extensions
    {
        private class Enumrable
        {
            private object Collection;
            private object Enumerator;

            private PropertyInfo Property_Current;
            private MethodInfo Method_MoveNext;

            public Enumrable(object enum_obj)
            {

                Collection = enum_obj;
                Type collection_type = Collection.GetType();

                try
                {
                    Enumerator = collection_type.GetMethod("GetEnumerator").Invoke(Collection, null);

                    Type enumerator_type = Enumerator.GetType();

                    Property_Current = enumerator_type.GetProperty("Current");
                    Method_MoveNext = enumerator_type.GetMethod("MoveNext");
                }
                catch
                {
                    throw new Exception(string.Format("{0} doesn't IEnumerable", enum_obj));
                }
            }

            public object Current
            {
                get
                {
                    return Property_Current.GetValue(Enumerator);
                }
            }
            public bool MoveNext()
            {
                return (bool)Method_MoveNext.Invoke(Enumerator, null);
            }
        }

        public static object[] EnumerableToObj(this object o)
        {
            List<object> res = new List<object>();

            Enumrable enumrable = new Enumrable(o);

            while (enumrable.MoveNext())
            {
                res.Add(enumrable.Current);
            }

            return res.ToArray();
        }

        public static List<KeyValuePair<object, object>> DictionaryToObj(this object o)
        {
            if (
                !o.GetType().IsGenericType
                || o.GetType().GetGenericTypeDefinition() != typeof(Dictionary<,>)
                )
                throw new Exception(string.Format("object {0} has type {1}. isn't Dictionary", o, o.GetType()));

            List <KeyValuePair <object, object>> res = new List<KeyValuePair<object, object>>();

            var ObjectArray = EnumerableToObj(o);

            if (ObjectArray.Length == 0)
                return res;

            Type ElemType = ObjectArray.FirstOrDefault().GetType();

            var PropertyKey = ElemType.GetProperty("Key");
            var PropertyValue = ElemType.GetProperty("Value");

            res.Capacity = ObjectArray.Length;

            for (int i = 0; i < ObjectArray.Length; i++)
            {
                res.Add(new KeyValuePair<object, object>(PropertyKey.GetValue(ObjectArray[i]), PropertyValue.GetValue(ObjectArray[i])));
            }

            return res;
        }

        public static Dictionary<object, object> objToDictionary(this object o)
        {
            if (
                !o.GetType().IsGenericType
                || o.GetType().GetGenericTypeDefinition() != typeof(Dictionary<,>)
                )
                throw new Exception(string.Format("object {0} has type {1}. isn't Dictionary", o, o.GetType()));

            Dictionary<object, object> res = new Dictionary<object, object>();

            System.Collections.IDictionary t = (System.Collections.IDictionary)o;
            foreach (var u in t.Keys)
                res.Add(u, t[u]);            

            return res;
        }
    }
}
