﻿// Copyright (c) Microsoft Open Technologies, Inc.  All rights reserved.
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 
// files (the "Software"), to deal  in the Software without restriction, including without limitation the rights  to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// WARRANTIES OF MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

namespace DataJS.Tests
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using Microsoft.OData.Service;
    using Microsoft.OData.Service.Common;
    using System.Globalization;
    using System.Linq;
    using System.Reflection;

    /// <summary>
    /// Provides a reflection-based, updatable data context.
    /// </summary>
    public abstract class ReflectionDataContext
    {
        // Fields
        private List<object> deletedObjects = new List<object>();
        private List<Action> pendingChanges;
        private static Dictionary<Type, Dictionary<string, IList>> resourceSetsByContextTypeStorage = new Dictionary<Type, Dictionary<string, IList>>();

        // Methods
        protected ReflectionDataContext()
        {
            this.MetadataHelper = new ReflectionMetadataHelper(this);
            this.pendingChanges = new List<Action>();
            if (!resourceSetsByContextTypeStorage.ContainsKey(base.GetType()))
            {
                resourceSetsByContextTypeStorage.Add(base.GetType(), new Dictionary<string, IList>());
                foreach (string resourceSetName in this.MetadataHelper.GetResourceSetNames())
                {
                    Type resourceType = this.MetadataHelper.GetResourceTypeOfSet(resourceSetName);
                    IList listOfTInstance = Activator.CreateInstance(typeof(List<>).MakeGenericType(new Type[] { resourceType })) as IList;
                    this.ResourceSetsStorage.Add(resourceSetName, listOfTInstance);
                }
            }
            this.EnsureDataIsInitialized();
        }

        public virtual void AddReferenceToCollection(object targetResource, string propertyName, object resourceToBeAdded)
        {
            ExceptionUtilities.CheckArgumentNotNull(targetResource, "targetResource");
            ExceptionUtilities.CheckArgumentNotNull(propertyName, "propertyName");
            ExceptionUtilities.CheckArgumentNotNull(resourceToBeAdded, "resourceToBeAdded");
            UpdatableToken targetToken = UpdatableToken.AssertIsToken(targetResource, "targetResource");
            targetResource = targetToken.Resource;
            resourceToBeAdded = UpdatableToken.AssertIsTokenAndResolve(resourceToBeAdded, "resourceToBeAdded");
            IList list = this.GetValue(targetToken, propertyName) as IList;
            ExceptionUtilities.CheckObjectNotNull(list, "Property '{0}' on type '{1}' was not a list", new object[] { propertyName, targetResource.GetType().Name });
            this.pendingChanges.Add(delegate {
                list.Add(resourceToBeAdded);
            });
        }

        public virtual void ClearChanges()
        {
            this.pendingChanges.Clear();
        }

        public void ClearData()
        {
            this.ResourceSetsStorage.Clear();
        }

        private static bool CompareETagValues(Dictionary<string, object> resourceCookieValues, IEnumerable<KeyValuePair<string, object>> concurrencyValues)
        {
            if (concurrencyValues.Count<KeyValuePair<string, object>>() != resourceCookieValues.Count)
            {
                return false;
            }
            foreach (KeyValuePair<string, object> keyValuePair in concurrencyValues)
            {
                if (!resourceCookieValues.ContainsKey(keyValuePair.Key))
                {
                    return false;
                }
                if (keyValuePair.Value == null)
                {
                    return (resourceCookieValues[keyValuePair.Key] == null);
                }
                if (!keyValuePair.Value.Equals(resourceCookieValues[keyValuePair.Key]))
                {
                    return false;
                }
            }
            return true;
        }

        public virtual object CreateResource(string containerName, string fullTypeName)
        {
            ExceptionUtilities.CheckArgumentNotNull(fullTypeName, "fullTypeName");
            UpdatableToken token = this.InstantiateResourceType(fullTypeName);
            if (containerName != null)
            {
                this.pendingChanges.Add(delegate {
                    this.GetResourceSetEntities(containerName).Add(token.Resource);
                });
            }
            return token;
        }

        private void DeleteAllReferences(object targetResource)
        {
            foreach (string currentSetName in this.MetadataHelper.GetResourceSetNames())
            {
                Type currentEntityType = this.MetadataHelper.GetResourceTypeOfSet(currentSetName);
                IList entitySetList = this.GetResourceSetEntities(currentSetName);
                foreach (NavigationPropertyInfo navigationProperty in this.MetadataHelper.GetNavigationProperties(GetResourceTypeFullName(currentEntityType)))
                {
                    if (navigationProperty.CollectionElementType != null)
                    {
                        foreach (object currentEntityInstance in entitySetList)
                        {
                            this.RemoveResourceFromCollectionOnTargetResourceMatch(targetResource, navigationProperty, currentEntityInstance);
                        }
                    }
                    else
                    {
                        ExceptionUtilities.CheckObjectNotNull(navigationProperty.PropertyInfo, "Invalid navigation property info", new object[0]);
                        foreach (object currentEntityInstance in entitySetList)
                        {
                            this.SetEntityReferenceToNullOnTargetResourceMatch(targetResource, navigationProperty, currentEntityInstance);
                        }
                    }
                }
            }
        }

        public virtual void DeleteResource(object targetResource)
        {
            ExceptionUtilities.CheckArgumentNotNull(targetResource, "targetResource");
            targetResource = UpdatableToken.AssertIsTokenAndResolve(targetResource, "targetResource");
            string resourceSetName = this.GetResourceSetOfTargetResource(targetResource);
            ExceptionUtilities.CheckObjectNotNull(resourceSetName, "Unable to find set of the resource to delete", new object[0]);
            this.deletedObjects.Add(targetResource);
            IList resourceSetList = this.GetResourceSetEntities(resourceSetName);
            this.DeleteAllReferences(targetResource);
            this.pendingChanges.Add(delegate {
                resourceSetList.Remove(targetResource);
            });
        }

        protected abstract void EnsureDataIsInitialized();

        protected virtual Type GetCollectionPropertyType(string fullTypeName, string propertyName)
        {
            Type type = this.MetadataHelper.FindClrTypeByFullName(fullTypeName);
            Type collectionType = null;
            if (type != null)
            {
                PropertyInfo property = type.GetProperty(propertyName);
                if (property != null)
                {
                    collectionType = property.PropertyType;
                }
            }
            return collectionType;
        }

        private Dictionary<string, object> GetConcurrencyValues(object targetResource)
        {
            Dictionary<string, object> etagValues = new Dictionary<string, object>();
            foreach (string etagProperty in this.MetadataHelper.GetETagPropertiesOfType(GetResourceTypeFullName(targetResource.GetType())))
            {
                etagValues.Add(etagProperty, targetResource.GetType().GetProperty(etagProperty).GetValue(targetResource, null));
            }
            return etagValues;
        }

        public virtual object GetResource(IQueryable query, string fullTypeName)
        {
            ExceptionUtilities.CheckArgumentNotNull(query, "query");
            object resource = null;
            foreach (object r in query)
            {
                ExceptionUtilities.Assert(resource == null, "Invalid Uri specified. The query '{0}' must refer to a single resource", new object[] { query.ToString() });
                resource = r;
            }
            if (resource == null)
            {
                return null;
            }
            if (fullTypeName != null)
            {
                this.ValidateResourceType(resource, fullTypeName);
            }
            return new UpdatableToken(resource);
        }

        public IList<T> GetResourceSetEntities<T>(string resourceSetName)
        {
            return (IList<T>) this.GetResourceSetEntities(resourceSetName);
        }

        internal IList GetResourceSetEntities(string resourceSetName)
        {
            IList entities;
            if (!this.ResourceSetsStorage.TryGetValue(resourceSetName, out entities))
            {
                Type elementType = this.MetadataHelper.GetResourceTypeOfSet(resourceSetName);
                entities = (IList) Activator.CreateInstance(typeof(List<>).MakeGenericType(new Type[] { elementType }));
                this.ResourceSetsStorage[resourceSetName] = entities;
            }
            return entities;
        }

        private string GetResourceSetOfTargetResource(object targetResource)
        {
            foreach (string currentResourceSetName in this.MetadataHelper.GetResourceSetNames())
            {
                if (this.GetResourceSetEntities(currentResourceSetName).Contains(targetResource))
                {
                    return currentResourceSetName;
                }
            }
            return null;
        }

        public static string GetResourceTypeFullName(Type type)
        {
            return type.FullName.Replace('+', '_');
        }

        public virtual object GetValue(object targetResource, string propertyName)
        {
            ExceptionUtilities.CheckArgumentNotNull(targetResource, "targetResource");
            ExceptionUtilities.CheckArgumentNotNull(propertyName, "propertyName");
            UpdatableToken token = UpdatableToken.AssertIsToken(targetResource, "targetResource");
            if (token.PendingPropertyUpdates.ContainsKey(propertyName))
            {
                return token.PendingPropertyUpdates[propertyName];
            }
            targetResource = token.Resource;
            PropertyInfo pi = targetResource.GetType().GetProperty(propertyName);
            ExceptionUtilities.CheckObjectNotNull(pi, "Cannot find the property '{0}' on type '{1}'", new object[] { propertyName, targetResource.GetType().Name });
            object value = pi.GetValue(targetResource, null);
            if ((value != null) && (pi.PropertyType.Assembly == base.GetType().Assembly))
            {
                ExceptionUtilities.Assert(!this.MetadataHelper.IsTypeAnEntityType(pi.PropertyType), "GetValue should never be called for reference properties. Type was '{0}', property was '{1}'", new object[] { pi.PropertyType.FullName, propertyName });
                value = new UpdatableToken(value);
            }
            return value;
        }

        private UpdatableToken InstantiateResourceType(string fullTypeName)
        {
            Type t = this.MetadataHelper.FindClrTypeByFullName(fullTypeName);
            object instance = Activator.CreateInstance(t);
            UpdatableToken token = new UpdatableToken(instance);
            foreach (PropertyInfo p in t.GetProperties())
            {
                object generatedValue;
                PropertyInfo property = p;
                if (this.IsCollectionProperty(property))
                {
                    Type collectionType = this.GetCollectionPropertyType(GetResourceTypeFullName(t), property.Name);
                    if (collectionType != null)
                    {
                        object newCollection = Activator.CreateInstance(collectionType);
                        token.PendingPropertyUpdates[property.Name] = newCollection;
                        this.pendingChanges.Add(delegate {
                            property.SetValue(instance, newCollection, null);
                        });
                    }
                }
                if (this.TryGetStoreGeneratedValue(fullTypeName, property.Name, out generatedValue))
                {
                    token.PendingPropertyUpdates[property.Name] = generatedValue;
                    this.pendingChanges.Add(delegate {
                        property.SetValue(instance, generatedValue, null);
                    });
                }
            }
            return token;
        }

        protected virtual bool IsCollectionProperty(PropertyInfo propertyInfo)
        {
            return ((typeof(IEnumerable).IsAssignableFrom(propertyInfo.PropertyType) && (propertyInfo.PropertyType != typeof(string))) && (propertyInfo.PropertyType != typeof(byte[])));
        }

        public virtual void RemoveReferenceFromCollection(object targetResource, string propertyName, object resourceToBeRemoved)
        {
            ExceptionUtilities.CheckArgumentNotNull(targetResource, "targetResource");
            ExceptionUtilities.CheckArgumentNotNull(propertyName, "propertyName");
            ExceptionUtilities.CheckArgumentNotNull(resourceToBeRemoved, "resourceToBeRemoved");
            UpdatableToken.AssertIsToken(targetResource, "targetResource");
            resourceToBeRemoved = UpdatableToken.AssertIsTokenAndResolve(resourceToBeRemoved, "resourceToBeRemoved");
            IList list = this.GetValue(targetResource, propertyName) as IList;
            ExceptionUtilities.CheckObjectNotNull(list, "Property '{0}' on type '{1}' was not a list", new object[] { propertyName, targetResource.GetType().Name });
            this.pendingChanges.Add(delegate {
                list.Remove(resourceToBeRemoved);
            });
        }

        private void RemoveResourceFromCollectionOnTargetResourceMatch(object targetResource, NavigationPropertyInfo navigationPropertyInfo, object currentEntityInstance)
        {
            IEnumerable childCollectionObject = navigationPropertyInfo.PropertyInfo.GetValue(currentEntityInstance, null) as IEnumerable;
            if (childCollectionObject.Cast<object>().Any<object>(delegate (object o) {
                return o == targetResource;
            }))
            {
                MethodInfo removeMethod = navigationPropertyInfo.PropertyInfo.PropertyType.GetMethod("Remove");
                this.pendingChanges.Add(delegate {
                    removeMethod.Invoke(childCollectionObject, new object[] { targetResource });
                });
            }
        }

        public virtual object ResetResource(object resource)
        {
            ExceptionUtilities.CheckArgumentNotNull(resource, "resource");
            UpdatableToken token = UpdatableToken.AssertIsToken(resource, "resource");
            resource = token.Resource;
            token = new UpdatableToken(resource);
            object newInstance = Activator.CreateInstance(resource.GetType());
            ExceptionUtilities.CheckObjectNotNull(newInstance, "Cannot reset resource because unable to creating new instance of type '{0}' returns null", new object[] { resource.GetType().Name });
            foreach (string propertyToReset in this.MetadataHelper.GetPropertiesToReset(GetResourceTypeFullName(resource.GetType())))
            {
                PropertyInfo pi = newInstance.GetType().GetProperty(propertyToReset);
                ExceptionUtilities.CheckObjectNotNull(pi, "Cannot reset resource because unable to find property '{0}'", new object[] { propertyToReset });
                object newValue = pi.GetValue(newInstance, null);
                this.pendingChanges.Add(delegate {
                    pi.SetValue(resource, newValue, null);
                });
                token.PendingPropertyUpdates[propertyToReset] = newValue;
            }
            return token;
        }

        public virtual object ResolveResource(object resource)
        {
            ExceptionUtilities.CheckArgumentNotNull(resource, "resource");
            return UpdatableToken.AssertIsTokenAndResolve(resource, "resource");
        }

        public virtual void SaveChanges()
        {
            foreach (Action pendingChange in this.pendingChanges)
            {
                pendingChange();
            }
            this.pendingChanges.Clear();
            foreach (object deleted in this.deletedObjects)
            {
                foreach (object entity in this.ResourceSetsStorage.SelectMany<KeyValuePair<string, IList>, object>(delegate (KeyValuePair<string, IList> p) {
                    return p.Value.Cast<object>();
                }))
                {
                    ExceptionUtilities.Assert(!object.ReferenceEquals(deleted, entity), "Found deleted entity!", new object[0]);
                    foreach (PropertyInfo propertyInfo in entity.GetType().GetProperties())
                    {
                        object value = propertyInfo.GetValue(entity, null);
                        ExceptionUtilities.Assert(!object.ReferenceEquals(deleted, value), "Found deleted entity!", new object[0]);
                        IEnumerable enumerable = value as IEnumerable;
                        if (enumerable != null)
                        {
                            foreach (object valueElement in enumerable.Cast<object>())
                            {
                                ExceptionUtilities.Assert(!object.ReferenceEquals(deleted, valueElement), "Found deleted entity!", new object[0]);
                            }
                        }
                    }
                }
            }
            this.deletedObjects.Clear();
        }

        protected virtual void SetCollectionPropertyValue(object targetResource, PropertyInfo propertyInfo, IEnumerable propertyValue)
        {
            object collection;
            ExceptionUtilities.CheckArgumentNotNull(targetResource, "targetResource");
            ExceptionUtilities.CheckArgumentNotNull(propertyInfo, "propertyInfo");
            ExceptionUtilities.CheckArgumentNotNull(propertyValue, "propertyValue");
            Type collectionType = this.GetCollectionPropertyType(GetResourceTypeFullName(propertyInfo.ReflectedType), propertyInfo.Name);
            ExceptionUtilities.CheckObjectNotNull(collectionType, "Could not infer collection type for property", new object[0]);
            propertyValue = propertyValue.Cast<object>().Select<object, object>(delegate (object o) {
                return UpdatableToken.ResolveIfToken(o);
            });
            ConstructorInfo enumerableConstructor = collectionType.GetConstructor(new Type[] { typeof(IEnumerable) });
            if (enumerableConstructor != null)
            {
                collection = enumerableConstructor.Invoke(new object[] { propertyValue });
            }
            else if (collectionType.IsGenericType && (collectionType.GetGenericArguments().Count<Type>() == 1))
            {
                Type typeArgument = collectionType.GetGenericArguments().Single<Type>();
                ConstructorInfo typedEnumerableConstructor = collectionType.GetConstructor(new Type[] { typeof(IEnumerable<>).MakeGenericType(new Type[] { typeArgument }) });
                if (typedEnumerableConstructor != null)
                {
                    object typedEnumerable = typeof(Enumerable).GetMethod("Cast").MakeGenericMethod(new Type[] { typeArgument }).Invoke(null, new object[] { propertyValue });
                    collection = typedEnumerableConstructor.Invoke(new object[] { typedEnumerable });
                }
                else
                {
                    MethodInfo typedAddMethod = collectionType.GetMethod("Add", new Type[] { typeArgument });
                    ExceptionUtilities.CheckObjectNotNull(typedAddMethod, "Could not find constructor or add method for type: " + collectionType.FullName, new object[0]);
                    collection = Activator.CreateInstance(collectionType);
                    foreach (object element in propertyValue)
                    {
                        typedAddMethod.Invoke(collection, new object[] { element });
                    }
                }
            }
            else
            {
                MethodInfo addMethod = collectionType.GetMethod("Add");
                ExceptionUtilities.CheckObjectNotNull(addMethod, "Could not find constructor or add method for type: " + collectionType.FullName, new object[0]);
                collection = Activator.CreateInstance(collectionType);
                foreach (object element in propertyValue)
                {
                    addMethod.Invoke(collection, new object[] { element });
                }
            }
            propertyInfo.SetValue(targetResource, collection, null);
        }

        public virtual void SetConcurrencyValues(object resourceCookie, bool? checkForEquality, IEnumerable<KeyValuePair<string, object>> concurrencyValues)
        {
            ExceptionUtilities.CheckArgumentNotNull(resourceCookie, "resourceCookie");
            ExceptionUtilities.ThrowDataServiceExceptionIfFalse(checkForEquality.HasValue, 0x1a1, "Missing concurrency token for update operation", new object[0]);
            ExceptionUtilities.Assert(checkForEquality.Value, "Should not be called with check for equality parameter equal to false", new object[0]);
            ExceptionUtilities.CheckArgumentNotNull(concurrencyValues, "concurrencyValues");
            if (concurrencyValues.Any<KeyValuePair<string, object>>())
            {
                resourceCookie = UpdatableToken.AssertIsTokenAndResolve(resourceCookie, "resourceCookie");
                ExceptionUtilities.ThrowDataServiceExceptionIfFalse(CompareETagValues(this.GetConcurrencyValues(resourceCookie), concurrencyValues), 0x19c, "Concurrency tokens do not match", new object[0]);
            }
        }

        private void SetEntityReferenceToNullOnTargetResourceMatch(object targetResource, NavigationPropertyInfo navigationPropertyInfo, object currentEntityInstance)
        {
            if (navigationPropertyInfo.PropertyInfo.GetValue(currentEntityInstance, null) == targetResource)
            {
                this.pendingChanges.Add(delegate {
                    navigationPropertyInfo.PropertyInfo.SetValue(currentEntityInstance, null, null);
                });
            }
        }

        public virtual void SetReference(object targetResource, string propertyName, object propertyValue)
        {
            ExceptionUtilities.CheckArgumentNotNull(targetResource, "targetResource");
            ExceptionUtilities.CheckArgumentNotNull(propertyName, "propertyName");
            if (propertyValue != null)
            {
                UpdatableToken.AssertIsToken(propertyValue, "propertyValue");
            }
            this.SetValue(targetResource, propertyName, propertyValue);
        }

        public virtual void SetValue(object targetResource, string propertyName, object propertyValue)
        {
            ExceptionUtilities.CheckArgumentNotNull(targetResource, "targetResource");
            ExceptionUtilities.CheckArgumentNotNull(propertyName, "propertyName");
            UpdatableToken token = UpdatableToken.AssertIsToken(targetResource, "targetResource");
            targetResource = token.Resource;
            token.PendingPropertyUpdates[propertyName] = propertyValue;
            this.pendingChanges.Add(delegate {
                object generatedValue;
                Type t = targetResource.GetType();
                PropertyInfo pi = t.GetProperty(propertyName);
                ExceptionUtilities.CheckObjectNotNull(pi, "Unable to find property '{0}' on type '{1}'", new object[] { propertyName, targetResource.GetType().Name });
                if (this.TryGetStoreGeneratedValue(GetResourceTypeFullName(t), propertyName, out generatedValue))
                {
                    propertyValue = generatedValue;
                }
                if (this.IsCollectionProperty(pi))
                {
                    ExceptionUtilities.CheckObjectNotNull(propertyValue, "Collection property value was null", new object[0]);
                    IEnumerable enumerable = propertyValue as IEnumerable;
                    ExceptionUtilities.CheckObjectNotNull(enumerable, "Collection property value was not an enumerable", new object[0]);
                    this.SetCollectionPropertyValue(targetResource, pi, enumerable);
                }
                else
                {
                    propertyValue = UpdatableToken.ResolveIfToken(propertyValue);
                    pi.SetValue(targetResource, propertyValue, null);
                }
            });
        }

        protected virtual bool TryGetStoreGeneratedValue(string fullTypeName, string propertyName, out object propertyValue)
        {
            propertyValue = null;
            return false;
        }

        private void ValidateResourceType(object targetResource, string fullTypeName)
        {
            ExceptionUtilities.Assert(this.MetadataHelper.FindClrTypeByFullName(fullTypeName).IsAssignableFrom(targetResource.GetType()), "Invalid uri specified. expected type: '{0}', actual type: '{1}'", new object[] { fullTypeName, targetResource.GetType().FullName });
        }

        // Properties
        internal ReflectionMetadataHelper MetadataHelper { get; set; }

        internal Dictionary<string, IList> ResourceSetsStorage
        {
            get
            {
                Dictionary<string, IList> resourceSetsLookup = null;
                Type currentContextType = base.GetType();
                ExceptionUtilities.Assert(resourceSetsByContextTypeStorage.TryGetValue(currentContextType, out resourceSetsLookup), "Cannot find resource sets by the context type '{0}'", new object[] { currentContextType });
                return resourceSetsLookup;
            }
        }

        #region Inner types.
    
        internal class ReflectionMetadataHelper
        {
            // Fields
            private ReflectionDataContext reflectionDataContext;

            // Methods
            public ReflectionMetadataHelper(ReflectionDataContext reflectionDataContext)
            {
                this.reflectionDataContext = reflectionDataContext;
            }

            public Type FindClrTypeByFullName(string resourceTypeFullName)
            {
                Type type = this.reflectionDataContext.GetType().Assembly.GetTypes().Where<Type>(delegate (Type t) {
                    return (ReflectionDataContext.GetResourceTypeFullName(t) == resourceTypeFullName);
                }).FirstOrDefault<Type>();
                ExceptionUtilities.CheckObjectNotNull(type, "Unable to find type '{0}'", new object[] { resourceTypeFullName });
                return type;
            }

            public string[] GetETagPropertiesOfType(string fullTypeName)
            {
                Type type = this.FindClrTypeByFullName(fullTypeName);
                List<string> etags = new List<string>();
                foreach (ETagAttribute customAttribute in type.GetCustomAttributes(typeof(ETagAttribute), true))
                {
                    etags.AddRange(customAttribute.PropertyNames);
                }
                
                return etags.ToArray();
            }

            public string[] GetKeyProperties(string fullTypeName)
            {
                Type type = this.FindClrTypeByFullName(fullTypeName);
                List<string> keyPropertyList = new List<string>();
                foreach (PropertyInfo keyProperty in type.GetProperties().Where(pi => pi.Name.Contains("ID")))
                {
                    keyPropertyList.Add(keyProperty.Name);
                }

                foreach (DataServiceKeyAttribute customAttribute in type.GetCustomAttributes(typeof(DataServiceKeyAttribute), true))
                {
                    keyPropertyList.AddRange(customAttribute.KeyNames);
                }
                
                return keyPropertyList.ToArray();
            }

            public NavigationPropertyInfo[] GetNavigationProperties(string fullTypeName)
            {
                Type type = this.FindClrTypeByFullName(fullTypeName);
                var navigationProperties = new List<NavigationPropertyInfo>();
                var keyProperties = new List<string>(this.GetKeyProperties(fullTypeName));
                foreach (PropertyInfo pi in type.GetProperties())
                {
                    if (!keyProperties.Contains(pi.Name))
                    {
                        if (this.IsTypeAnEntityType(pi.PropertyType))
                        {
                            navigationProperties.Add(new NavigationPropertyInfo(pi, null));
                        }

                        if (pi.PropertyType.IsGenericType && ((pi.PropertyType.GetGenericTypeDefinition() == typeof(List<>)) || (pi.PropertyType.GetGenericTypeDefinition() == typeof(Collection<>))))
                        {
                            Type elementType = pi.PropertyType.GetGenericArguments()[0];
                            if (this.IsTypeAnEntityType(elementType))
                            {
                                navigationProperties.Add(new NavigationPropertyInfo(pi, elementType));
                            }
                        }
                    }
                }

                return navigationProperties.ToArray();
            }

            public string[] GetPropertiesToReset(string fullTypeName)
            {
                Type type = this.FindClrTypeByFullName(fullTypeName);
                var keyProperties = new List<string>(this.GetKeyProperties(fullTypeName));
                var navigationProperties = new List<string>(this.GetNavigationProperties(fullTypeName).Select(ni =>ni.PropertyInfo.Name));
                return type.GetProperties().Where(
                    pi => !keyProperties.Contains(pi.Name) && !navigationProperties.Contains(pi.Name)
                ).Select(pi => pi.Name).ToArray();
            }

            public string[] GetResourceSetNames()
            {
                return this.reflectionDataContext.GetType().GetProperties().Where(
                    pi => pi.PropertyType.IsGenericType && (pi.PropertyType.GetGenericTypeDefinition() == typeof(IQueryable<>))
                ).Select(pi => pi.Name).ToArray();
            }

            public Type GetResourceTypeOfSet(string resourceSetName)
            {
                PropertyInfo resourceSetPropertyInfo = this.reflectionDataContext.GetType().GetProperties().Where(pi => pi.Name == resourceSetName).FirstOrDefault();
                ExceptionUtilities.CheckObjectNotNull(resourceSetPropertyInfo, "Error finding type of set '{0}'", new object[] { resourceSetName });
                return resourceSetPropertyInfo.PropertyType.GetGenericArguments()[0];
            }

            public bool IsTypeAnEntityType(Type t)
            {
                foreach (string setName in this.GetResourceSetNames())
                {
                    if (this.GetResourceTypeOfSet(setName).IsAssignableFrom(t))
                    {
                        return true;
                    }
                }

                return false;
            }
        }

        internal static class ExceptionUtilities
        {
            // Methods
            public static void Assert(bool condition, string errorMessage, params object[] messageArguments)
            {
                if (!condition)
                {
                    throw new InvalidOperationException("Assertion failed: " + string.Format(CultureInfo.InvariantCulture, errorMessage, messageArguments));
                }
            }

            public static void CheckArgumentNotNull(object argument, string argumentName)
            {
                if (argument == null)
                {
                    throw new ArgumentNullException(argumentName);
                }
            }

            public static void CheckCollectionNotEmpty<TElement>(IEnumerable<TElement> argument, string argumentName)
            {
                CheckArgumentNotNull(argument, argumentName);
                if (!argument.Any<TElement>())
                {
                    throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "Collection argument '{0}' must have at least one element.", new object[] { argumentName }));
                }
            }

            public static void CheckObjectNotNull(object value, string exceptionMessageFormatText, params object[] messageArguments)
            {
                Assert(exceptionMessageFormatText != null, "message cannnot be null", new object[0]);
                Assert(messageArguments != null, "messageArguments cannnot be null", new object[0]);
                if (value == null)
                {
                    throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, exceptionMessageFormatText, messageArguments));
                }
            }

            public static void ThrowDataServiceExceptionIfFalse(bool condition, int statusCode, string errorMessage, params object[] messageArguments)
            {
                if (!condition)
                {
                    throw new DataServiceException(statusCode, string.Format(CultureInfo.InvariantCulture, errorMessage, messageArguments));
                }
            }
        }

        public class UpdatableToken
        {
            // Methods
            public UpdatableToken(object resource)
            {
                ExceptionUtilities.CheckArgumentNotNull(resource, "resource");
                this.Resource = resource;
                this.PendingPropertyUpdates = new Dictionary<string, object>();
            }

            public static UpdatableToken AssertIsToken(object resource, string name)
            {
                ExceptionUtilities.CheckArgumentNotNull(resource, "resource");
                UpdatableToken token = resource as UpdatableToken;
                ExceptionUtilities.CheckObjectNotNull(token, "{0} was not a token. Type was: '{1}'", new object[] { name, resource.GetType() });
                return token;
            }

            public static object AssertIsTokenAndResolve(object resource, string name)
            {
                return AssertIsToken(resource, name).Resource;
            }

            public static object ResolveIfToken(object resource)
            {
                UpdatableToken token = resource as UpdatableToken;
                if (token != null)
                {
                    resource = token.Resource;
                }
                return resource;
            }

            // Properties
            public IDictionary<string, object> PendingPropertyUpdates { get; set; }

            public object Resource { get; set; }
        }

        internal class NavigationPropertyInfo
        {
            // Methods
            internal NavigationPropertyInfo(PropertyInfo pi, Type collectionElementType)
            {
                this.PropertyInfo = pi;
                this.CollectionElementType = collectionElementType;
            }

            // Properties
            public Type CollectionElementType { get; set; }

            public PropertyInfo PropertyInfo { get; set; }
        }

        #endregion Inner types.
    }
}