using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;

namespace LinqAnalyzer
{
	[DiagnosticAnalyzer(LanguageNames.CSharp)]
	public class LinqAnalyzerAnalyzer : DiagnosticAnalyzer
	{
		public const string DiagnosticId = "LinqAnalyzer";

		private static readonly LocalizableString Title = new LocalizableResourceString(nameof(Resources.AnalyzerTitle), Resources.ResourceManager, typeof(Resources));
		private static readonly LocalizableString MessageFormat = new LocalizableResourceString(nameof(Resources.AnalyzerMessageFormat), Resources.ResourceManager, typeof(Resources));
		private static readonly LocalizableString Description = new LocalizableResourceString(nameof(Resources.AnalyzerDescription), Resources.ResourceManager, typeof(Resources));
		private const string Category = "Naming";

		private static DiagnosticDescriptor Rule = new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, Category, DiagnosticSeverity.Warning, isEnabledByDefault: true, description: Description);

		public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get { return ImmutableArray.Create(Rule); } }

		public override void Initialize(AnalysisContext context)
		{
			context.RegisterSyntaxNodeAction(AnalyzeLinq, SyntaxKind.InvocationExpression);
		}

		private static void AnalyzeLinq(SyntaxNodeAnalysisContext context)
		{
			var expression = (InvocationExpressionSyntax)context.Node;
			if (expression.Parent is EqualsValueClauseSyntax || expression.Parent is AssignmentExpressionSyntax)
				return;
			var semanticModel = context.SemanticModel;
			var typeInfo = semanticModel.GetTypeInfo(expression);
			var type = typeInfo.Type as INamedTypeSymbol;
			if (type.Name.Equals("IEnumerable", StringComparison.Ordinal) 
				&& type.TypeArguments.Length == 1)
			{
				context.ReportDiagnostic(Diagnostic.Create(Rule, expression.GetLocation(), type.TypeArguments[0].Name));
			}
		}
	}
}
