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

using static System.Console;
using System.Linq;
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;

namespace ex_042_017_EF_concurrency_problematic
{
    /// <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
    {
        /// <summary>
        /// récupère un Nounours à partir de son id
        /// </summary>
        /// <param name="id">l'id du Nounours à récupérer</param>
        /// <returns>le Nounours récupéré (null, si l'id n'est pas connu dans la base)</returns>
        static Nounours GetNounours(Guid id)
        {
            Nounours nounours = null;

            using (NounoursDBEntities db = new NounoursDBEntities())
            {
                nounours = db.NounoursSet.Single(n => n.UniqueId == id);
            }

            return nounours;
        }

        /// <summary>
        /// mise à jour du Nounours dans la base
        /// </summary>
        /// <param name="nounours">nounours à mettre à jour</param>
        static void UpdateNounours(Nounours nounours)
        {
            using (NounoursDBEntities db = new NounoursDBEntities())
            {
                db.NounoursSet.Attach(nounours);
                db.Entry<Nounours>(nounours).State = EntityState.Modified;

                db.SaveChanges();
            }
        }

        static void Main(string[] args)
        {
            List<Guid> ids = new List<Guid>();

            //création du DbContext et injection de la dépendance à MyStubDataInitializationStrategy
            using (NounoursDBEntities db = new NounoursDBEntities())
            {
                //choix de la stratégie et remplissage avec des données stubbées
                DbContextInitializer.Seed(db);

                //récupère la liste des ids
                ids = db.NounoursSet.Select(n => n.UniqueId).ToList();
            }

            PrintTable("Au démarrage, la table contient :");

            WriteLine();

            //DEBUT DE LA SIMULATION DE MISES A JOUR CONCURRENTES

            //1. Le premier utilisateur récupère les données du premier nounours
            Nounours nounours1 = GetNounours(ids[0]);
            WriteLine("L'utilisateur 1 récupère le premier nounours");

            //2. Le deuxième utilisateur réupère les données du premier nounours
            Nounours nounours2 = GetNounours(ids[0]);
            WriteLine("L'utilisateur 2 récupère le premier nounours");

            //jusque-là, la table contient :
            // "Chewbacca", 27/05/1977, 1234567 poils
            // "Yoda", 21/05/1980, 3 poils
            // "Ewok", 25/05/1983, 3456789 poils

            //3. Le premier utilisateur tente de mettre à jour le nombre de poils
            nounours1.NbPoils = 2;
            UpdateNounours(nounours1);
            PrintTable("Après la tentative de modification du nombre de poils de Chewbacca à 2 par l'utilisateur 1 :");

            //maintenant, la table contient :
            // "Chewbacca", 27/05/1977, 2 poils <==========================
            // "Yoda", 21/05/1980, 3 poils
            // "Ewok", 25/05/1983, 3456789 poils

            //4. Le deuxième utilisateur tente de mettre à jour la propriété Date De Naissance
            nounours2.DateDeNaissance = DateTime.Today;
            UpdateNounours(nounours2);
            PrintTable("Après la tentative de modification de la date de naissance de Chewbacca à aujourd'hui par l'utilisateur 2 :");

            //maintenant, la table contient :
            // "Chewbacca", 07/11/2016, 1234567 poils <===========================
            // "Yoda", 21/05/1980, 3 poils
            // "Ewok", 25/05/1983, 3456789 poils

            //Remarquez que le nombre de poils a été écrasé par la propriété précédente, car le deuxième utilisateur a récupéré le nounours avant la première modification.
        }

        static void PrintTable(string intro)
        {
            WriteLine();
            WriteLine(intro);
            using (NounoursDBEntities db = new NounoursDBEntities())
            {
                //affiche les nounours après les modifications
                WriteLine("Après modifications");
                foreach (var n in db.NounoursSet)
                {
                    WriteLine($"\t{n}");
                }
            }
        }
    }
}
