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

using static System.Console;

namespace ex_019_001_interfaces
{
    //interface
    //notez le mot clé interface
    interface IMediaObjet
    {
        //une interface ne possède pas de champs et ses méthodes et propriétés ne sont pas implémentées

        //les méthodes, propriétés, indexeurs et événements ne donnent pas l'accessibilité (public, private, internal, protected)
        //Cette accessibilité est implicitement publique.
        //En conséquence, les classes implémentant l'interface devront obligatoirement implémenter les méthodes, propriétés, indexeurs et événements
        //déclarés par l'interface comme publiques
        void Affiche();

        string Titre
        {
            get;
        }
    }

    interface IMusiqueObjet
    {
        string Producteur
        {
            get;
        }
    }



    //une classe fille
    class Livre : IMediaObjet
    {
        protected string mTitre;
        protected int mAnnéeCréation;
        private string mAuteur;

        public Livre(string titre, int année, string auteur)
        {
            mTitre = titre;
            mAnnéeCréation = année;
            mAuteur = auteur;
        }

        //pas besoin de préciser override
        public void Affiche()
        {
            WriteLine($"Le livre {mTitre} a été écrit par {mAuteur} en {mAnnéeCréation}");
        }

        public string Titre
        {
            get
            {
                return mTitre;
            }
        }
    }

    //on peut implémenter plusieurs interfaces
    class Disque : IMediaObjet, IMusiqueObjet
    {
        private string mArtiste;
        protected string mTitre;
        protected int mAnnéeCréation;
        private string mProducteur;

        public Disque(string titre, int année, string artiste, string producteur)
        {
            mTitre = titre;
            mAnnéeCréation = année;
            mArtiste = artiste;
            mProducteur = producteur;
        }

        //pas besoin de préciser override
        public void Affiche()
        {
            WriteLine($"Le disque {mTitre} a été enregistré par {mArtiste} en {mAnnéeCréation}, et produit par {mProducteur}");
        }

        public string Titre
        {
            get
            {
                return mTitre;
            }
            private set
            {
                mTitre = value;
            }
        }

        public string Producteur
        {
            get
            {
                return mProducteur;
            }
        }

    }

    //les structures aussi peuvent implémenter des interfaces
    struct Film : IMediaObjet
    {
        string mTitre;

        public Film(string titre)
        {
            mTitre = titre;
        }

        public string Titre
        {
            get
            {
                return mTitre;
            }
        }
        public void Affiche()
        {
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            OutputEncoding = System.Text.Encoding.UTF8;
           
            //l est de type Livre (construit avec Livre) et appelle Affiche de Livre
            Livre l = new Livre("Attenti al Gorilla", 1995, "Sandrone Dazieri");
            l.Affiche();

            //d est de type Disque (construit avec Disque) et appelle Affiche de Disque
            Disque d = new Disque("Tommy", 1969, "The Who", "Kit Lambert");
            d.Affiche();

            //on ne peut pas appeler le constructeur de IMediaObjet car c'est une interface
            //IMediaObjet mo = new IMediaObjet();
            //mo.Affiche();

            //mo2 implémente IMediaObjet et est construit avec le constructeur de Livre, il appelle Affiche de Livre
            //même si mo2 est de type IMediaObjet(interface), comme il a été construit avec une classe concrète (Livre), il n'y a pas d'erreurs
            IMediaObjet mo2 = new Livre("Attenti al Gorilla", 1995, "Sandrone Dazieri");
            mo2.Affiche();
            //mo3 implémente IMediaObjet et est construit avec le constructeur de Disque, il appelle Affiche de Disque
            //même si mo3 est de type IMediaObjet(interface), comme il a été construit avec une classe concrète (Disque), il n'y a pas d'erreurs
            IMediaObjet mo3 = new Disque("Tommy", 1969, "The Who", "Kit Lambert");
            mo3.Affiche();
            //avec les méthodes virtuelles, lors de l'exécution, le véritable type est testé.




            //on peut aussi vérifier avec is ou as qu'un objet implémente une interface
            if (l is IMusiqueObjet)
            {
                WriteLine($"{l.Titre} implémente l'interface IMusiqueObjet");
            }
            else
            {
                WriteLine($"{l.Titre} n'implémente pas l'interface");
            }
            if (d is IMusiqueObjet)
            {
                WriteLine($"{d.Titre} implémente l'interface IMusiqueObjet");
            }
            else
            {
                WriteLine($"{d.Titre} n'implémente pas l'interface");
            }

        }
    }
}
