using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using Prime31.Reflection;

namespace Prime31
{
	// Token: 0x0200001C RID: 28
	public class PocoJsonSerializerStrategy : IJsonSerializerStrategy
	{
		// Token: 0x060000AA RID: 170 RVA: 0x0000749C File Offset: 0x0000569C
		public PocoJsonSerializerStrategy()
		{
			this.cacheResolver = new CacheResolver(new MemberMapLoader(this.buildMap));
		}

		// Token: 0x060000AB RID: 171 RVA: 0x000074C0 File Offset: 0x000056C0
		protected virtual void buildMap(Type type, SafeDictionary<string, CacheResolver.MemberMap> memberMaps)
		{
			foreach (PropertyInfo propertyInfo in type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
			{
				memberMaps.add(propertyInfo.Name, new CacheResolver.MemberMap(propertyInfo));
			}
			foreach (FieldInfo fieldInfo in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
			{
				memberMaps.add(fieldInfo.Name, new CacheResolver.MemberMap(fieldInfo));
			}
		}

		// Token: 0x060000AC RID: 172 RVA: 0x00007544 File Offset: 0x00005744
		public virtual bool serializeNonPrimitiveObject(object input, out object output)
		{
			return this.trySerializeKnownTypes(input, out output) || this.trySerializeUnknownTypes(input, out output);
		}

		// Token: 0x060000AD RID: 173 RVA: 0x00007574 File Offset: 0x00005774
		public virtual object deserializeObject(object value, Type type)
		{
			object obj = null;
			if (value is string)
			{
				string text = value as string;
				if (!string.IsNullOrEmpty(text) && (type == typeof(DateTime) || (ReflectionUtils.isNullableType(type) && Nullable.GetUnderlyingType(type) == typeof(DateTime))))
				{
					obj = DateTime.ParseExact(text, PocoJsonSerializerStrategy.Iso8601Format, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal);
				}
				else
				{
					obj = text;
				}
			}
			else if (value is bool)
			{
				obj = value;
			}
			else if (value == null)
			{
				obj = null;
			}
			else if ((value is long && type == typeof(long)) || (value is double && type == typeof(double)))
			{
				obj = value;
			}
			else
			{
				if ((!(value is double) || type == typeof(double)) && (!(value is long) || type == typeof(long)))
				{
					if (value is IDictionary<string, object>)
					{
						IDictionary<string, object> dictionary = (IDictionary<string, object>)value;
						if (ReflectionUtils.isTypeDictionary(type))
						{
							Type type2 = type.GetGenericArguments()[0];
							Type type3 = type.GetGenericArguments()[1];
							Type type4 = typeof(Dictionary<, >).MakeGenericType(new Type[]
							{
								type2,
								type3
							});
							IDictionary dictionary2 = (IDictionary)CacheResolver.getNewInstance(type4);
							foreach (KeyValuePair<string, object> keyValuePair in dictionary)
							{
								dictionary2.Add(keyValuePair.Key, this.deserializeObject(keyValuePair.Value, type3));
							}
							obj = dictionary2;
						}
						else
						{
							obj = CacheResolver.getNewInstance(type);
							SafeDictionary<string, CacheResolver.MemberMap> safeDictionary = this.cacheResolver.loadMaps(type);
							if (safeDictionary == null)
							{
								obj = value;
							}
							else
							{
								foreach (KeyValuePair<string, CacheResolver.MemberMap> keyValuePair2 in safeDictionary)
								{
									CacheResolver.MemberMap value2 = keyValuePair2.Value;
									if (value2.Setter != null)
									{
										string key = keyValuePair2.Key;
										if (dictionary.ContainsKey(key))
										{
											object value3 = this.deserializeObject(dictionary[key], value2.Type);
											value2.Setter(obj, value3);
										}
									}
								}
							}
						}
					}
					else if (value is IList<object>)
					{
						IList<object> list = (IList<object>)value;
						IList list2 = null;
						if (type.IsArray)
						{
							list2 = (IList)Activator.CreateInstance(type, new object[]
							{
								list.Count
							});
							int num = 0;
							foreach (object value4 in list)
							{
								list2[num++] = this.deserializeObject(value4, type.GetElementType());
							}
						}
						else if (ReflectionUtils.isTypeGenericeCollectionInterface(type) || typeof(IList).IsAssignableFrom(type))
						{
							Type type5 = type.GetGenericArguments()[0];
							Type type6 = typeof(List<>).MakeGenericType(new Type[]
							{
								type5
							});
							list2 = (IList)CacheResolver.getNewInstance(type6);
							foreach (object value5 in list)
							{
								list2.Add(this.deserializeObject(value5, type5));
							}
						}
						obj = list2;
					}
					return obj;
				}
				obj = ((!typeof(IConvertible).IsAssignableFrom(type)) ? value : Convert.ChangeType(value, type, CultureInfo.InvariantCulture));
			}
			object result;
			if (ReflectionUtils.isNullableType(type))
			{
				result = ReflectionUtils.toNullableType(obj, type);
			}
			else
			{
				result = obj;
			}
			return result;
		}

		// Token: 0x060000AE RID: 174 RVA: 0x000079E0 File Offset: 0x00005BE0
		protected virtual object serializeEnum(Enum p)
		{
			return Convert.ToDouble(p, CultureInfo.InvariantCulture);
		}

		// Token: 0x060000AF RID: 175 RVA: 0x00007A08 File Offset: 0x00005C08
		protected virtual bool trySerializeKnownTypes(object input, out object output)
		{
			bool result = true;
			if (input is DateTime)
			{
				output = ((DateTime)input).ToUniversalTime().ToString(PocoJsonSerializerStrategy.Iso8601Format[0], CultureInfo.InvariantCulture);
			}
			else if (input is Guid)
			{
				output = ((Guid)input).ToString("D");
			}
			else if (input is Uri)
			{
				output = input.ToString();
			}
			else if (input is Enum)
			{
				output = this.serializeEnum((Enum)input);
			}
			else
			{
				result = false;
				output = null;
			}
			return result;
		}

		// Token: 0x060000B0 RID: 176 RVA: 0x00007AB8 File Offset: 0x00005CB8
		protected virtual bool trySerializeUnknownTypes(object input, out object output)
		{
			output = null;
			Type type = input.GetType();
			bool result;
			if (type.FullName == null)
			{
				result = false;
			}
			else
			{
				IDictionary<string, object> dictionary = new JsonObject();
				SafeDictionary<string, CacheResolver.MemberMap> safeDictionary = this.cacheResolver.loadMaps(type);
				foreach (KeyValuePair<string, CacheResolver.MemberMap> keyValuePair in safeDictionary)
				{
					if (keyValuePair.Value.Getter != null)
					{
						dictionary.Add(keyValuePair.Key, keyValuePair.Value.Getter(input));
					}
				}
				output = dictionary;
				result = true;
			}
			return result;
		}

		// Token: 0x0400004F RID: 79
		internal CacheResolver cacheResolver;

		// Token: 0x04000050 RID: 80
		private static readonly string[] Iso8601Format = new string[]
		{
			"yyyy-MM-dd\\THH:mm:ss.FFFFFFF\\Z",
			"yyyy-MM-dd\\THH:mm:ss\\Z",
			"yyyy-MM-dd\\THH:mm:ssK"
		};
	}
}
