using System;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using EFCore5.Convenience;
using EFCore5.Counters;
using EFCore5.EntititesToQueries;
using EFCore5.M2MMapping;
using EFCore5.Migrations;
using EFCore5.MoreMapping;
using EFCore5.PropertyBags;
using EFCore5.QueryImprovements;
using EFCore5.QueryUpdate;
using EFCore5.RequiredOneOnOneDependents;
using EFCore5.TPT;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Migrations;

namespace EFCore5
{
	class Program
	{
		static void Main(string[] args)
		{
			//using (var db = new M2MContext())
			//{
			//	db.Database.EnsureDeleted();
			//	db.Database.EnsureCreated();

			//	db.Owners.Include(x => x.Dogs).Load();
			//}
			//using (var db = new TPTContext())
			//{
			//	db.Database.EnsureDeleted();
			//	db.Database.EnsureCreated();
			//}
			//using (var db = new EntitiesToQueriesContext())
			//{
			//	db.Database.EnsureDeleted();
			//	db.Database.EnsureCreated();

			//	db.Set<EntityQuery>().Where(x => x.Bar == 1).Load();
			//}
			//using (var db = new QueryUpdateContext())
			//{
			//	db.Database.EnsureDeleted();
			//	db.Database.EnsureCreated();

			//	//db.Set<QueryUpdateEntity>().Where(x => x.Foo == "aaa").Load();
			//	db.Set<QueryUpdateEntity>().Add(new QueryUpdateEntity() { Foo = "bbb" });
			//	db.SaveChanges();
			//}
			//using (var db = new PropertyBagsContext())
			//{
			//	db.Database.EnsureDeleted();
			//	db.Database.EnsureCreated();

			//	//db.Dogs.Where(x => (string)x["Name"] == "Clif").Load();
			//	db.PropertyBagDogs.Where(x => (string)x["Name"] == "Clif").Load();
			//}
			//using (var db = new RequiredOneOnOneDependentsContext())
			//{
			//	db.Database.EnsureDeleted();
			//	db.Database.EnsureCreated();
			//}
			//using (var db = new ConvenienceContext())
			//{
			//	db.Database.EnsureDeleted();
			//	db.Database.EnsureCreated();

			//	db.SavingChanges += (object sender, SavingChangesEventArgs e) => { };
			//	db.SavedChanges += (object sender, SavedChangesEventArgs e) => { };
			//	db.SaveChangesFailed += (object sender, SaveChangesFailedEventArgs e) => { };

			//	var sql = db.Dogs.Where(x => x.Name == "Clif").ToQueryString();
			//	WriteLine(sql, ConsoleColor.Yellow);
			//}
			//using (var db = new QueryImprovementsContext())
			//{
			//	db.Database.EnsureDeleted();
			//	db.Database.EnsureCreated();

			//	db.Dogs.Add(new Dog() { Name = "test", Created = DateTimeOffset.UtcNow });
			//	db.SaveChanges();

			//	// UseSqlServer -> UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery)
			//	db.Dogs.AsSplitQuery().Include(x => x.Owners).TagWith("split").Load();
			//	db.Dogs.AsSingleQuery().Include(x => x.Owners).TagWith("single").Load();
			//	db.Dogs.Include(x => x.Owners.Where(y => y.LastName == "aaa")).TagWith("filter").Load();

			//	db.Dogs.AsNoTrackingWithIdentityResolution().Load();

			//	// null handling
			//	// more DateTime constructs
			//	// Reverse
			//	// byte array
			//	// bitwise op
			//	db.Dogs.Where(x => x.Name.FirstOrDefault() == 'a').Load();
			//}
			//{
			//	WriteLine($"dotnet counters monitor Microsoft.EntityFrameworkCore -p {Environment.ProcessId}", ConsoleColor.Yellow);
			//	Console.ReadLine();
			//	ThreadPool.QueueUserWorkItem(_ => Do());
			//	ThreadPool.QueueUserWorkItem(_ => Do());
			//	ThreadPool.QueueUserWorkItem(_ => Do());
			//	Console.ReadLine();
			//	static void Do()
			//	{
			//		var random = new Random();
			//		while (true)
			//		{
			//			using (var db = new CountersContext())
			//			{
			//				db.Dogs.Where(x => 0 != 1).Load();
			//				db.Dogs.AddRange(new[]
			//				{
			//					new Dog() { Name = "test1", Created = DateTimeOffset.UtcNow },
			//					new Dog() { Name = "test2", Created = DateTimeOffset.UtcNow },
			//					new Dog() { Name = "test3", Created = DateTimeOffset.UtcNow },
			//					new Dog() { Name = "test4", Created = DateTimeOffset.UtcNow },
			//				});
			//				db.SaveChanges();
			//				db.Dogs.Where(x => 0 != 2).Load();
			//			}
			//			Thread.Sleep(random.Next(0, 500));
			//		}
			//	}
			//}
			//{
			//	// dotnet ef migrations add <NAME> --namespace
			//	// dotnet ef migrations add Test -o "Migrations\Alter" -c BoundedContext --namespace "Migrations.Changes"
			//	using (var db = new BoundedContext())
			//	{
			//		WriteLine(db.GetService<IMigrator>().GenerateScript(null, null, MigrationsSqlGenerationOptions.NoTransactions | MigrationsSqlGenerationOptions.Idempotent | MigrationsSqlGenerationOptions.Script), ConsoleColor.Yellow);
			//		WriteLine(new string('=', 80), ConsoleColor.Cyan);
			//		WriteLine(db.GetService<IMigrator>().GenerateScript(null, null, MigrationsSqlGenerationOptions.Idempotent | MigrationsSqlGenerationOptions.Script), ConsoleColor.Yellow);
			//	}
			//}
			//using (var db = new MoreMappingContext())
			//{
			//	db.Database.EnsureDeleted();
			//	db.Database.EnsureCreated();

			//	db.Set<Dog>().OrderBy(x => EF.Functions.Collate(x.Name, "German_PhoneBook_CI_AS")).Load();

			//	db.Set<Dog>().Select(x => new
			//	{
			//		Name = x.Name,
			//		TVF = db.CallTVF(x.Id).FirstOrDefault(),
			//	}).Load();
			//}
			//{
			//	using (var db = new ElementaryDbContext())
			//	{
			//		// IDbContextFactory<ElementaryDbContext>()
			//		// AddDbContextFactory
			//		// AddPooledDbContextFactory

			//		// reset DbContext -> ChangeTracker.Clear()

			//		using (var tx = db.Database.BeginTransaction())
			//		{
			//			db.SaveChanges();
			//			tx.CreateSavepoint("MySavePoint");
			//			db.SaveChanges();
			//			tx.Commit();
			//			// tx.RollbackToSavepoint("MySavePoint");
			//		}

			//		// db.Database.SetConnectionString
			//		// db.Database.SetDbConnection

			//		// INotifyPropertyChanging + INotifyPropertyChanged change tracking proxies
			//	}
			//}
			{
				// Cosmos
				// builder.Entity<E>().Property(x => x.ETag).IsEtagConcurrency();
				// builder.Entity<E>().HasPartitionKey(x => x.AlternateKey);
				/*
					optionsBuilder
						.UseCosmos("my-cosmos-connection-string", "MyDb",
							cosmosOptionsBuilder =>
							{
								cosmosOptionsBuilder.LimitToEndpoint();
								cosmosOptionsBuilder.RequestTimeout(requestTimeout);
								cosmosOptionsBuilder.OpenTcpConnectionTimeout(timeout);
								cosmosOptionsBuilder.IdleTcpConnectionTimeout(timeout);
								cosmosOptionsBuilder.GatewayModeMaxConnectionLimit(connectionLimit);
								cosmosOptionsBuilder.MaxTcpConnectionsPerEndpoint(connectionLimit);
								cosmosOptionsBuilder.MaxRequestsPerTcpConnection(requestLimit);
							});
				 */
			}
		}

		public static void WriteLine(string message, ConsoleColor? color = null)
		{
			var oldColor = Console.ForegroundColor;
			try
			{
				Console.ForegroundColor = color ?? Console.ForegroundColor;
				Console.WriteLine(message);
			}
			finally
			{
				Console.ForegroundColor = oldColor;
			}
		}
	}
}
