// ========================================================================
//
// Copyright (C) 2016-2017 MARC CHEVALDONNE
//                         marc.chevaldonne.free.fr
//
// Module        : Program.cs
// Author        : Marc Chevaldonné
// Creation date : 2016-11-11
//
// ========================================================================

using static System.Console;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;

namespace ex_042_016_EF_current_original_database_val
{
    /// <summary>
    /// Cet exemple montre à quoi correspondent les valeurs CurrrentValues, OriginalValues et DabaseValues et comment les obtenir depuis Entity Framework Core.
    /// Ici, on montre donc une entrée dans la base dont la propriété Nom est modifiée.
    /// </summary>
    class Program
    {
        public static void PrintValues(EntityEntry<Nounours> entry, NounoursDBEntities context, Values values)
        {
            foreach (var property in entry.Metadata.GetProperties())
            {
                switch(values)
                {
                    case Values.Current:
                        WriteLine($"La propriété {property.Name} a la valeur {entry.Property(property.Name).CurrentValue}");
                        break;
                    case Values.Original:
                        WriteLine($"La propriété {property.Name} a la valeur {entry.Property(property.Name).OriginalValue}");
                        break;
                    case Values.Database:
                        // Using a NoTracking query means we get the entity but it is not tracked by the context
                        // and will not be merged with existing entities in the context.
                        var databaseEntity = context.NounoursSet.AsNoTracking().Single(n => n.UniqueId == (entry.Entity as Nounours).UniqueId);
                        //récupère l'entry correspondante dans la base
                        var databaseEntry = context.Entry(databaseEntity);
                        WriteLine($"La propriété {property.Name} a la valeur {databaseEntry.Property(property.Name).CurrentValue}");
                        break;
                }
            }
        }

        public enum Values
        {
            Current,
            Original,
            Database
        }

        static void Main(string[] args)
        {
            using (var context = new NounoursDBEntities())
            {
                //choix de la stratégie et remplissage avec des données stubbées
                DbContextInitializer.Seed(context);

                var ids = context.NounoursSet.Select(n => n.UniqueId).ToList();

                //on récupère le premier Nounours
                var nounours = context.NounoursSet.Single(n => n.UniqueId == ids[0]);

                // On réalise une modification de la propriété Nom de l'entité récupérée 
                nounours.Nom = "Chewie";

                // Pendant ce temps, l'entité correspondante en base de données est modifiée (la colonne Nom)
                context.Database.ExecuteSqlCommand($"update dbo.TableNounours set Nom = 'Boule de poils' where UniqueId = {ids[0]}");

                // Affichage des données dites "courantes" CurrentValues 
                WriteLine("Current values:");
                PrintValues(context.Entry(nounours), context, Values.Current);

                // Affichage des données dites "originales" OriginalValues 
                WriteLine("\nOriginal values:");
                PrintValues(context.Entry(nounours), context, Values.Original);//.OriginalValues);

                // Affichage des données dites "base de données" DatabaseValues 
                WriteLine("\nDatabase values:");
                PrintValues(context.Entry(nounours), context, Values.Database);//.GetDatabaseValues());

                WriteLine();
                WriteLine("Remarquez que CurrentValues correspond aux données de l'entité en cours de modification,");
                WriteLine("Remarquez que OriginalValues correspond aux données de l'entité récupérée juste avant modification,");
                WriteLine("Remarquez que DatabaseValues correspond aux données de l'entité telles que sont en bas de données.");
            }
        }
    }
}
