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

using System;
using static System.Console;

namespace ex_016_002_properties
{
    class Nounours
    {
        //une propriété ressemble à un champ de l'extérieur mais se comporte comme une méthode à l'intérieur
        //on l'utilise comme accesseur sur un champ privé pour garantir l'encapsulation
        //en lecture/écriture, lecture ou écriture
        //on l'associe donc généralement à un champ privé
        public string Nom
        {
            get //public string GetNom()
            {
                return mNom;
            }
            set //public void SetNom(string value)
            {
                mNom = value;
            }
        }
        private string mNom;

        //on peut en conséquence, protéger nos champs privés de différentes manières
        public int Taille
        {
            get
            {
                return mTaille;
            }
            set
            {
                if (value > 0)
                {
                    mTaille = value;
                }
            }
        }
        private int mTaille = 100;

        //on peut aussi avoir une propriété en lecture seule
        public DateTime DateDeNaissance
        {
            get
            {
                return mDateDeNaissance;
            }
        }
        private DateTime mDateDeNaissance;

        //ou en écriture seule

        //automatic properties
        //on peut aussi définir une propriété sans membre privé si le getter et le setter sont basiques (aux modifiers près)
        //(ne marche pas sur les structures)
        public int Poils
        {
            get;
            private set;
        }

        //calculated properties
        //une propriété n'est pas forcément liée à un membre privé (ou protégé), elle est peut être calculée à partir d'autres membres ou propriétés
        public float PoilsParCm
        {
            get
            {
                return (float)Poils / Taille;
            }
        }

        //expression-bodied read-only properties (C#6)
        // une propriété calculée ou read-only peut aussi être déclarée directement à l'aide d'une expression
        // notez qu'il n'est plus nécessaire d'utiliser les { }, le mot-clef get, et le mot-clef return
        public int Age => DiffYears + (DateDeNaissance.AddYears(DiffYears) > DateTime.Today ? -1 : 0);
        //et une petite propriété privée rapide pour simplifier l'écriture de la propriété précédente
        private int DiffYears => DateTime.Today.Year - DateDeNaissance.Year;

        // depuis C#6 on peut également initialiser une propriété automatique juste après l'avoir écrite.
        // C'est notamment très pratique pour les propriétés automatiques en lecture seule.
        public string Odeur { get; set; } = "chien mouillé";

        public Nounours(string nom, int taille, DateTime naissance, int poils)
        {
            Nom = nom;
            Taille = taille;
            mDateDeNaissance = naissance;
            Poils = poils;
        }

        //propriété statique
        public static string Définition
        {
            get
            {
                return mDéfinition;
            }
            set
            {
                mDéfinition = value;
            }
        }
        private static string mDéfinition = "Mot enfantin pour désigner un ours en peluche";
    }

    class Program
    {
        static void Main(string[] args)
        {
            OutputEncoding = System.Text.Encoding.UTF8;
         
            //les propriétés s'utilisent comme des membres
            Nounours nounours = new Nounours("ours", 42, new DateTime(2015, 9, 26), 30000);
            WriteLine("Nounours nounours = new Nounours(\"ours\", 42, DateTime.Today, 30000);");
            WriteLine($"Nom : {nounours.Nom}");
            WriteLine($"Poils : {nounours.Poils}");
            WriteLine($"Taille : {nounours.Taille}");
            WriteLine($"Age : {nounours.Age}");
            WriteLine($"Odeur : {nounours.Odeur}");
            WriteLine($"Date de naissance : {nounours.DateDeNaissance}");
            WriteLine($"Poils par cm : {nounours.PoilsParCm}");
            WriteLine("nounours.Taille = 41;");
            nounours.Taille = 41;
            WriteLine($"Taille : {nounours.Taille}");
            WriteLine($"Poils par cm : {nounours.PoilsParCm}");
            WriteLine($"Définition : {Nounours.Définition}");
        }
    }
}
