// We don't do SerializedPropertyType.Generic or SerializedPropertyType.ArraySize because we are never gonna have an array of those.
// We can't have an array of any generic type (List, Array, Dictionary, etc) because Unity doesn't serialize nested/jagged/multidimensional
// collections, and only serializes Lists and Arrays.
public static T[] GetArray<T>(this SerializedProperty property, bool getLong = false, bool getDouble = false)
{
	if (property == null)
	{
		throw new ArgumentException($"SerializedProperty is null");
	}

	if (property.isArray == false)
	{
		throw new ArgumentException($"{property.name} is not an array property");
	}

	if (property.arraySize == 0)
	{
		return null;
	}

	T[] array = new T[property.arraySize];

	switch (property.GetArrayElementAtIndex(0).propertyType)
	{
		case SerializedPropertyType.Integer:
			{
				for (int i = 0; i < array.Length; i++)
				{
					if (getLong)
					{
						array[i] = (T)(object)property.GetArrayElementAtIndex(i).longValue;
					}
					else
					{
						array[i] = (T)(object)property.GetArrayElementAtIndex(i).intValue;
					}
				}
			}
			break;
		case SerializedPropertyType.Boolean:
			{
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = (T)(object)property.GetArrayElementAtIndex(i).boolValue;
				}
			}
			break;
		case SerializedPropertyType.Float:
			{
				for (int i = 0; i < array.Length; i++)
				{
					if (getDouble)
					{
						array[i] = (T)(object)property.GetArrayElementAtIndex(i).doubleValue;
					}
					else
					{
						array[i] = (T)(object)property.GetArrayElementAtIndex(i).floatValue;
					}
				}
			}
			break;
		case SerializedPropertyType.String:
			{
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = (T)(object)property.GetArrayElementAtIndex(i).stringValue;
				}
			}
			break;
		case SerializedPropertyType.Color:
			{
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = (T)(object)property.GetArrayElementAtIndex(i).colorValue;
				}
			}
			break;
		case SerializedPropertyType.LayerMask:
			{
				for (int i = 0; i < array.Length; i++)
				{
					LayerMask temp = property.GetArrayElementAtIndex(i).intValue;
					array[i] = (T)(object)temp;
				}
			}
			break;
		case SerializedPropertyType.Enum:
			{
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = (T)(object)property.GetArrayElementAtIndex(i).enumValueIndex;
				}
			}
			break;
		case SerializedPropertyType.Vector2:
			{
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = (T)(object)property.GetArrayElementAtIndex(i).vector2Value;
				}
			}
			break;
		case SerializedPropertyType.Vector3:
			{
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = (T)(object)property.GetArrayElementAtIndex(i).vector3Value;
				}
			}
			break;
		case SerializedPropertyType.Vector4:
			{
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = (T)(object)property.GetArrayElementAtIndex(i).vector4Value;
				}
			}
			break;
		case SerializedPropertyType.Rect:
			{
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = (T)(object)property.GetArrayElementAtIndex(i).rectValue;
				}
			}
			break;
		case SerializedPropertyType.Character:
			{
				for (int i = 0; i < array.Length; i++)
				{
					char c = Convert.ToChar(property.GetArrayElementAtIndex(i).intValue);
					array[i] = (T)(object)c;
				}
			}
			break;
		case SerializedPropertyType.AnimationCurve:
			{
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = (T)(object)property.GetArrayElementAtIndex(i).animationCurveValue;
				}
			}
			break;
		case SerializedPropertyType.Bounds:
			{
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = (T)(object)property.GetArrayElementAtIndex(i).boundsValue;
				}
			}
			break;
		case SerializedPropertyType.Gradient:
			{
				for (int i = 0; i < array.Length; i++)
				{
					SerializedPropertyWrapper wrapper = new SerializedPropertyWrapper(property.GetArrayElementAtIndex(i));
					array[i] = (T)wrapper.gradientValue;
				}
			}
			break;
		case SerializedPropertyType.Quaternion:
			{
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = (T)(object)property.GetArrayElementAtIndex(i).quaternionValue;
				}
			}
			break;
		case SerializedPropertyType.FixedBufferSize:
			{
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = (T)(object)property.GetArrayElementAtIndex(i).fixedBufferSize;
				}
			}
			break;
		case SerializedPropertyType.Vector2Int:
			{
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = (T)(object)property.GetArrayElementAtIndex(i).vector2IntValue;
				}
			}
			break;
		case SerializedPropertyType.Vector3Int:
			{
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = (T)(object)property.GetArrayElementAtIndex(i).vector3IntValue;
				}
			}
			break;
		case SerializedPropertyType.RectInt:
			{
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = (T)(object)property.GetArrayElementAtIndex(i).rectIntValue;
				}
			}
			break;
		case SerializedPropertyType.BoundsInt:
			{
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = (T)(object)property.GetArrayElementAtIndex(i).boundsIntValue;
				}
			}
			break;
		case SerializedPropertyType.ObjectReference:
			{
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = (T)(object)property.GetArrayElementAtIndex(i).objectReferenceValue;
				}
			}
			break;
		//case SerializedPropertyType.ExposedReference:
		//	break;
		//case SerializedPropertyType.ManagedReference:
		//	break;
		default:
			break;
	}

	return array;
}