/// <summary>
        ///
        /// </summary>
        /// <param name="fieldName"></param>
        /// <param name="recordType"></param>
        /// <param name="dependantValue">Various uses...</param>
        /// <param name="record">The record containing the field we are getting the options for</param>
        /// <returns></returns>
        public override IEnumerable <PicklistOption> GetPicklistKeyValues(string fieldName, string recordType, string dependantValue, IRecord record)
        {
            //if the property is type RecordType
            //then get the record types from the lookup service
            var fieldType = this.GetFieldType(fieldName, recordType);

            switch (fieldType)
            {
            case RecordFieldType.RecordType:
            {
                var lookupService = GetLookupService(fieldName, recordType, dependantValue, record);

                if (OptionSetLimitedValues != null &&
                    OptionSetLimitedValues.ContainsKey(fieldName) &&
                    OptionSetLimitedValues[fieldName].Any())
                {
                    return(OptionSetLimitedValues[fieldName]
                           .Select(at => new RecordType(at, LookupService.GetRecordTypeMetadata(at).DisplayName))
                           .OrderBy(rt => rt.Value)
                           .ToArray());
                }
                else
                {
                    return(lookupService == null
                                ? new RecordType[0]
                                : lookupService.GetAllRecordTypes()
                           .Select(r => new RecordType(r, lookupService.GetRecordTypeMetadata(r).DisplayName))
                           .ToArray());
                }
            }

            case RecordFieldType.RecordField:
            {
                if (dependantValue == null)
                {
                    return(new RecordField[0]);
                }

                var    options         = new List <PicklistOption>();
                var    type            = dependantValue;
                string parentReference = null;
                if (dependantValue != null && dependantValue.Contains(':'))
                {
                    type            = ((string)dependantValue).Split(':').ElementAt(0);
                    parentReference = ((string)dependantValue).Split(':').ElementAt(1);
                }
                var lookupService = GetLookupService(fieldName, recordType, parentReference, record);

                var allFieldsMetadata = type.IsNullOrWhiteSpace() || lookupService == null
                            ? new IFieldMetadata[0]
                            : lookupService
                                        .GetFieldMetadata(type);
                var propertyInfo     = GetPropertyInfo(fieldName, recordType);
                var lookupConditions = propertyInfo.GetCustomAttributes <LookupCondition>();
                foreach (var condition in lookupConditions.Select(lc => lc.ToCondition()))
                {
                    allFieldsMetadata =
                        allFieldsMetadata.Where(f => MeetsCondition(f, condition)).ToArray();
                }
                var onlyInclude = OptionSetLimitedValues == null || !OptionSetLimitedValues.ContainsKey(fieldName)
                            ? null
                            : OptionSetLimitedValues[fieldName];

                return(allFieldsMetadata
                       .Select(f => new RecordField(f.SchemaName, f.DisplayName))
                       .Where(f => !f.Value.IsNullOrWhiteSpace())
                       .Where(f => onlyInclude == null || onlyInclude.Contains(f.Key))
                       .OrderBy(f => f.Value)
                       .ToArray());
            }

            case RecordFieldType.Picklist:
            {
                var type    = GetPropertyType(fieldName, recordType);
                var options = new List <PicklistOption>();
                if (type.Name == "IEnumerable`1")
                {
                    type = type.GenericTypeArguments[0];
                }
                foreach (Enum item in type.GetEnumValues())
                {
                    var enumMember             = item.GetType().GetMember(item.ToString()).First();
                    var validForFieldAttribute = enumMember.GetCustomAttribute <ValidForFieldTypes>();
                    if (validForFieldAttribute == null || dependantValue == null)
                    {
                        options.Add(PicklistOption.EnumToPicklistOption(item));
                    }
                    else
                    {
                        if (validForFieldAttribute.FieldTypes.Contains(dependantValue.ParseEnum <RecordFieldType>()))
                        {
                            options.Add(PicklistOption.EnumToPicklistOption(item));
                        }
                    }
                }
                var propertyInfo   = GetPropertyInfo(fieldName, recordType);
                var limitAttribute = propertyInfo.GetCustomAttribute <LimitPicklist>();
                if (limitAttribute != null)
                {
                    options =
                        options.Where(
                            o =>
                            limitAttribute.ToInclude.Select(kv => Convert.ToInt32(kv).ToString())
                            .Contains(o.Key))
                        .ToList();
                }
                return(options);
            }
            }
            throw new ArgumentOutOfRangeException(
                      string.Format("GetPicklistOptions Not Implemented For Fiel Of Type {0} Field: {1} Type {2}", fieldType,
                                    fieldName, recordType));
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="fieldName"></param>
        /// <param name="recordType"></param>
        /// <param name="dependantValue">Various uses...</param>
        /// <param name="record">The record containing the field we are getting the options for</param>
        /// <returns></returns>
        public override IEnumerable <PicklistOption> GetPicklistKeyValues(string fieldName, string recordType, string dependantValue, IRecord record)
        {
            //if the property is type RecordType
            //then get the record types from the lookup service
            var fieldType = this.GetFieldType(fieldName, recordType);

            switch (fieldType)
            {
            case RecordFieldType.RecordType:
            {
                var lookupService = GetLookupService(fieldName, recordType, dependantValue, record);

                if (OptionSetLimitedValues != null &&
                    OptionSetLimitedValues.ContainsKey(fieldName) &&
                    OptionSetLimitedValues[fieldName].Any())
                {
                    return(OptionSetLimitedValues[fieldName]
                           .Select(at => new RecordType(at, LookupService.GetRecordTypeMetadata(at).DisplayName))
                           .OrderBy(rt => rt.Value)
                           .ToArray());
                }
                else
                {
                    if (lookupService == null)
                    {
                        return(new RecordType[0]);
                    }
                    var recordTypes     = lookupService.GetAllRecordTypes();
                    var includeExplicit = new[] { "subject", "uom", "productpricelevel", "activitymimeattachment" };
                    var options         = recordTypes
                                          .Select(rt => lookupService.GetRecordTypeMetadata(rt))
                                          .Where(mt => mt.Searchable || includeExplicit.Contains(mt.SchemaName))
                                          .Select(mt => new RecordType(mt.SchemaName, mt.DisplayName))
                                          .ToList();
                    var classType = GetClassType(recordType);
                    var prop      = classType.GetProperty(fieldName);
                    if (prop.GetCustomAttribute <IncludeManyToManyIntersects>() != null)
                    {
                        var manyToManys = lookupService.GetManyToManyRelationships();
                        foreach (var manyToMany in manyToManys)
                        {
                            if (!options.Any(p => p.Key == manyToMany.IntersectEntityName))
                            {
                                options.Add(new RecordType(manyToMany.IntersectEntityName, manyToMany.PicklistDisplay));
                            }
                        }
                    }
                    var exclusionAttribute = prop.GetCustomAttribute <RecordTypeExclusions>();
                    if (exclusionAttribute != null)
                    {
                        options.RemoveAll(o => exclusionAttribute.RecordTypes.Contains(o.Key));
                    }
                    options.RemoveAll(o => string.IsNullOrWhiteSpace(o.Value));
                    return(options);
                }
            }

            case RecordFieldType.RecordField:
            {
                if (dependantValue == null)
                {
                    return(new RecordField[0]);
                }

                var    options         = new List <PicklistOption>();
                var    type            = dependantValue;
                string parentReference = null;
                if (dependantValue != null && dependantValue.Contains(':'))
                {
                    type            = ((string)dependantValue).Split(':').ElementAt(0);
                    parentReference = ((string)dependantValue).Split(':').ElementAt(1);
                }
                var lookupService = GetLookupService(fieldName, recordType, parentReference, record);

                var allFieldsMetadata = type.IsNullOrWhiteSpace() || lookupService == null
                            ? new IFieldMetadata[0]
                            : lookupService
                                        .GetFieldMetadata(type);
                var propertyInfo     = GetPropertyInfo(fieldName, recordType);
                var lookupConditions = propertyInfo.GetCustomAttributes <LookupCondition>();
                foreach (var condition in lookupConditions.Select(lc => lc.ToCondition()))
                {
                    allFieldsMetadata =
                        allFieldsMetadata.Where(f => MeetsCondition(f, condition)).ToArray();
                }
                var onlyInclude = OptionSetLimitedValues == null || !OptionSetLimitedValues.ContainsKey(fieldName)
                            ? null
                            : OptionSetLimitedValues[fieldName];

                return(allFieldsMetadata
                       .Select(f => new RecordField(f.SchemaName, f.IsPrimaryKey ? f.DisplayName + " Id" : f.DisplayName))
                       .Where(f => !f.Value.IsNullOrWhiteSpace())
                       .Where(f => onlyInclude == null || onlyInclude.Contains(f.Key))
                       .OrderBy(f => f.Value)
                       .ToArray());
            }

            case RecordFieldType.Picklist:
            {
                var type    = GetPropertyType(fieldName, recordType);
                var options = new List <PicklistOption>();
                if (type.Name == "IEnumerable`1")
                {
                    type = type.GenericTypeArguments[0];
                }
                foreach (Enum item in type.GetEnumValues())
                {
                    var enumMember             = item.GetType().GetMember(item.ToString()).First();
                    var validForFieldAttribute = enumMember.GetCustomAttribute <ValidForFieldTypes>();
                    if (validForFieldAttribute == null || dependantValue == null)
                    {
                        options.Add(PicklistOption.EnumToPicklistOption(item));
                    }
                    else
                    {
                        var dependencySplit = dependantValue.Split('|');
                        var fieldTypeEnum   = dependencySplit[0].ParseEnum <RecordFieldType>();
                        var supplementaryDependencyArguments = dependencySplit.Length == 1 || dependencySplit[1] == ""
                                    ? null
                                    : dependencySplit[1].Split(',');

                        if (validForFieldAttribute.FieldTypes.Contains(fieldTypeEnum))
                        {
                            if (validForFieldAttribute.IntegerType.HasValue)
                            {
                                if (supplementaryDependencyArguments != null &&
                                    supplementaryDependencyArguments.Contains(validForFieldAttribute.IntegerType.Value.ToString()))
                                {
                                    options.Add(PicklistOption.EnumToPicklistOption(item));
                                }
                            }
                            else if (validForFieldAttribute.TargetType != null)
                            {
                                if (supplementaryDependencyArguments != null &&
                                    supplementaryDependencyArguments.Contains(validForFieldAttribute.TargetType))
                                {
                                    options.Add(PicklistOption.EnumToPicklistOption(item));
                                }
                            }
                            else if (validForFieldAttribute.TargetType == null || supplementaryDependencyArguments == null)
                            {
                                options.Add(PicklistOption.EnumToPicklistOption(item));
                            }
                        }
                    }
                }
                var propertyInfo   = GetPropertyInfo(fieldName, recordType);
                var limitAttribute = propertyInfo.GetCustomAttribute <LimitPicklist>();
                if (limitAttribute != null)
                {
                    options =
                        options.Where(
                            o =>
                            limitAttribute.ToInclude.Select(kv => Convert.ToInt32(kv).ToString())
                            .Contains(o.Key))
                        .ToList();
                }
                return(options);
            }
            }
            return(null);
        }