using System;
using System.Collections.Generic;
using System.Linq;
using FluentNHibernate.Cfg;
using HibernatingRhinos.Profiler.Appender;
using HibernatingRhinos.Profiler.Appender.NHibernate;
using NHibernate.Cfg;
using NHibernate.Cfg.Loquacious;
using NHibernate.Criterion;
using NHibernate.Dialect;
using NHibernate.Driver;
using NHibernate.Linq;
using NHibernate.Tool.hbm2ddl;

namespace NHibernateHacking
{
    class Program
    {
        static void Main() {
            NHibernateProfiler.Initialize();

            var cfg = new Configuration();
            cfg.DataBaseIntegration(x => {
                                        x.ConnectionStringName = "Default";
                                        x.Driver<SqlClientDriver>();
                                        x.Dialect<MsSql2008Dialect>();
                                        x.BatchSize = 50;
//                                        x.LogSqlInConsole = true;
                                    });
//            cfg.AddAssembly(Assembly.GetExecutingAssembly());

            Fluently.Configure(cfg)
                    .Mappings(x => x.FluentMappings
                                    .AddFromAssemblyOf<Customer>())
                    .BuildConfiguration();

            var exporter = new SchemaExport(cfg);
            exporter.Execute(false, true, false);

            var sessionFactory = cfg.BuildSessionFactory();
            var savedId = Guid.Empty;
            Customer jane = null;
            using(var session = sessionFactory.OpenSession())
            using(var tx = session.BeginTransaction()) {
                var order1 = new Order{LineItems={new LineItem(), new LineItem(), new LineItem()}};
                var order2 = new Order();
                var customer = new Customer {Name = "John Doe"};
                customer.AddOrder(order1);
                customer.AddOrder(order2);
//                Console.WriteLine("Before save:");
//                Console.WriteLine(customer);
                session.Save(customer);
                jane = new Customer {Name="Jane Smith"};
                session.Save(jane);
                tx.Commit();
                savedId = jane.Id;
                ProfilerInfrastructure.FlushAllMessages();
//                Console.WriteLine("After save:");
//                Console.WriteLine(customer);
            }

            using(var session = sessionFactory.OpenSession())
            using(var tx = session.BeginTransaction()) {
//                var janeAgain = session.Load<Customer>(savedId);
//                var janeReloaded = session.Get<Customer>(savedId);
//                Console.WriteLine(janeReloaded);
//                Console.WriteLine(janeAgain);
//                Console.WriteLine(ReferenceEquals(janeReloaded, janeAgain));
//                Console.WriteLine(ReferenceEquals(jane, janeAgain));
//                foreach(var order in janeAgain.Orders) {
//                    Console.WriteLine(order.Id);
//                    foreach(var lineItem in order.LineItems) {
//                        Console.WriteLine(lineItem);
//                    }
//                }
//                var query = session.CreateQuery("select c, count(c.Orders) from Customer c");
//                query.SetParameter("name", "Jane Smith");
//                var customers = query.List<Customer>();
//                foreach(var customer in customers) {
//                    Console.WriteLine(customer);
//                }
//                var stats = query.List();
//                foreach(object[] stat in stats) {
//                    Console.WriteLine(stat[0] + "\t" + stat[1]);
//                }
                var query = session.CreateCriteria<Customer>()
                                    .Add(Expression.Eq("Name", "Jane Smith"))
                                    .Future<Customer>();
                var query2 = session.QueryOver<Customer>()
                                    .Where(x => x.Name == "John Doe")
                                    .Future();
                var query3 = (from c in session.Query<Customer>()
                              where c.Name == "Jane Smith"
                              select c)
                             .ToFuture();
                foreach(var customer in query) {
                    Console.WriteLine(customer);
                }
                foreach(var customer in query2) {
                    Console.WriteLine(customer);
                }
                foreach(var customer in query3) {
                    Console.WriteLine(customer);
                }

                var example = Example.Create(new Customer{Name="Jane Smith"});
                var exampleQuery = session.CreateCriteria<Customer>()
                                     .Add(example).List<Customer>();
                foreach(var customer in exampleQuery) {
                    Console.WriteLine(customer);
                }

                var query4 = from c in session.Query<Customer>()
                             select new {c.Name};
                foreach(var customer in query4.ToList()) {
                    Console.WriteLine(customer);
                }

                tx.Commit();
            }

            Console.WriteLine("Press <ENTER> to exit...");
            Console.ReadLine();
        }
    }
}

