using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reactive.Linq;
using System.Reflection;

namespace System.Reactive
{
	internal class ObservableQueryProvider : GInterface5, IQueryProvider
	{
		public IQbservable<TResult> CreateQuery<TResult>(Expression expression)
		{
			if (expression == null)
			{
				throw new ArgumentNullException("expression");
			}
			if (!typeof(IObservable<TResult>).IsAssignableFrom(expression.Type))
			{
				throw new ArgumentException(Strings_Providers.INVALID_TREE_TYPE, "expression");
			}
			return new ObservableQuery<TResult>(expression);
		}

		IQueryable<TElement> IQueryProvider.CreateQuery<TElement>(Expression expression)
		{
			MethodCallExpression methodCallExpression = expression as MethodCallExpression;
			if (methodCallExpression == null || methodCallExpression.Method.DeclaringType != typeof(Qbservable) || methodCallExpression.Method.Name != "ToQueryable")
			{
				throw new ArgumentException(Strings_Providers.EXPECTED_TOQUERYABLE_METHODCALL, "expression");
			}
			Expression expression2 = methodCallExpression.Arguments[0];
			return Expression.Lambda<Func<IQueryable<TElement>>>(Expression.Call(ObservableQueryProvider.AsQueryable.MakeGenericMethod(new Type[] { typeof(TElement) }), Expression.Call(typeof(Observable).GetMethod("ToEnumerable").MakeGenericMethod(new Type[] { typeof(TElement) }), expression2)), Array.Empty<ParameterExpression>()).Compile()();
		}

		private static MethodInfo AsQueryable
		{
			get
			{
				if (ObservableQueryProvider._staticAsQueryable == null)
				{
					ObservableQueryProvider._staticAsQueryable = Qbservable.InfoOf<object>(Expression.Lambda<Func<object>>(Expression.Call(null, methodof(IEnumerable<!!0>.AsQueryable()), new Expression[] { Expression.Constant(null, typeof(IEnumerable<object>)) }), Array.Empty<ParameterExpression>())).GetGenericMethodDefinition();
				}
				return ObservableQueryProvider._staticAsQueryable;
			}
		}

		IQueryable IQueryProvider.CreateQuery(Expression expression)
		{
			throw new NotImplementedException();
		}

		TResult IQueryProvider.Execute<TResult>(Expression expression)
		{
			throw new NotImplementedException();
		}

		object IQueryProvider.Execute(Expression expression)
		{
			throw new NotImplementedException();
		}

		private static MethodInfo _staticAsQueryable;
	}
}
