using System;
using System.Collections.Generic;
 
namespace DoFactory.GangOfFour.Prototype.RealWorld
{
  /// 
  /// MainApp startup class for Real-World 
  /// Prototype Design Pattern.
  /// 
  class MainApp
  {
	/// 
	/// Entry point into console application.
	/// 
    static void Main()
    {
      ColorManager colormanager = new ColorManager();
 
      // Initialize with standard colors

      colormanager["red"] = new Color(255, 0, 0);
      colormanager["green"] = new Color(0, 255, 0);
      colormanager["blue"] = new Color(0, 0, 255);
 
      // User adds personalized colors

      colormanager["angry"] = new Color(255, 54, 0);
      colormanager["peace"] = new Color(128, 211, 128);
      colormanager["flame"] = new Color(211, 34, 20);
 
      // User clones selected colors

      Color color1 = colormanager["red"].Clone() as Color;
      Color color2 = colormanager["peace"].Clone() as Color;
      Color color3 = colormanager["flame"].Clone() as Color;
 
      // Wait for user

      Console.ReadKey();
    }
  }
 
  /// 
  /// The 'Prototype' abstract class
  /// 
  abstract class ColorPrototype
  {
    public abstract ColorPrototype Clone();
  }
 
  /// 
  /// The 'ConcretePrototype' class
  /// 
  class Color : ColorPrototype
  {
    private int _red;
    private int _green;
    private int _blue;
 
    // Constructor
    public Color(int red, int green, int blue)
    {
      this._red = red;
      this._green = green;
      this._blue = blue;
    }
 
    // Create a shallow copy
    public override ColorPrototype Clone()
    {
      Console.WriteLine(
        "Cloning color RGB: {0,3},{1,3},{2,3}",
        _red, _green, _blue);
 
      return this.MemberwiseClone() as ColorPrototype;
    }
  }
 
  /// 
  /// Prototype manager
  /// 
  class ColorManager
  {
    private Dictionary _colors = new Dictionary();
 
    // Indexer
    public ColorPrototype this[string key]
    {
      get { return _colors[key]; }
      set { _colors.Add(key, value); }
    }
  }
}