using System;
using System.Collections.Generic;
using System.Text;

namespace AdvancedEvent
{
   delegate void NameChangedDelegate(string name, string newValue);

   class Program
   {
      static void Main(string[] args)
      {
         Customer c = new Customer();
         Subscriber s1 = new Subscriber(c, "subskrybent-A");
         Subscriber s2 = new Subscriber(c, "subskrybent-B");
         Subscriber s3 = new Subscriber(c, "subskrybent-C");

         c.FirstName = "Kevin";
         c.LastName = "Hoffman";

         s2.Unsubscribe();

         c.FirstName = "Joe";

         c.MiddleName = "Scott";

         Console.ReadLine();
      }

   }

   class Subscriber
   {
      private string subscriberId = "nowy subskrybent";
      private Customer myCustomer = null;
      private NameChangedDelegate ncDel = null;

      public Subscriber(Customer c, string subId)
      {
         subscriberId = subId;
         ncDel = new NameChangedDelegate(myCustomer_OnNameChanged);
         myCustomer = c;
         myCustomer.OnNameChanged += ncDel;
      }

      void myCustomer_OnNameChanged(string name, string newValue)
      {
         Console.WriteLine("[{0}] Klient {1} zmieniono na {2}.", subscriberId,
            name, newValue);
      }

      public void Unsubscribe()
      {
         myCustomer.OnNameChanged -= ncDel;
      }

      public string SubscriberID
      {
         get
         {
            return subscriberId;
         }
         set
         {
            subscriberId = value;
         }
      }
   }

   class Customer
   {
      private string firstName;
      private string lastName;
      private string middleName;
      private event NameChangedDelegate onNameChange;

      public event NameChangedDelegate OnNameChanged
      {
         add
         {
            onNameChange += value;
            if (value.Target is Subscriber)
            {
               Console.WriteLine(
                  "Subskrybent '{0}' właśnie subskrybował zdarzenie OnNameChanged.",
                  ((Subscriber)value.Target).SubscriberID);
            }
         }
         remove
         {
            onNameChange -= value;
            if (value.Target is Subscriber)
            {
               Console.WriteLine(
                 "Subskrybent '{0}' właśnie zrezygnował z subskrypcji zdarzenia OnNameChanged.",
                 ((Subscriber)value.Target).SubscriberID);
            }
         }
      }

      public string FirstName
      {
         get
         {
            return firstName;
         }
         set
         {
            firstName = value;
            onNameChange("imię", value);
         }
      }

      public string LastName
      {
         get
         {
            return lastName;
         }
         set
         {
            lastName = value;
            onNameChange("nazwisko", value);
         }
      }

      public string MiddleName
      {
         get
         {
            return MiddleName;
         }
         set
         {
            middleName = value;
            NotifyAllBut("subskrybent-C", "drugie imię", value);
         }
      }

      private void NotifyAllBut(string subId, string name, string value)
      {
         foreach (NameChangedDelegate d in onNameChange.GetInvocationList())
         {
            if (((Subscriber)d.Target).SubscriberID.ToUpper() != subId.ToUpper())
            {
               d(name, value);
            }
         }
      }
   }
}
