using System;
using System.Collections.Generic;

namespace IComparer
{
	public class Employee : IComparable<Employee>
	{
		private int empID;

		private int yearsOfSvc = 1;

		public Employee(int empID)
		{
			this.empID = empID;
		}


		public Employee(int empID, int yearsOfSvc)
		{
			this.empID = empID;
			this.yearsOfSvc = yearsOfSvc;
		}

		public override string ToString()
		{
			return "ID: " + empID.ToString() +
			". Liczba lat: " + yearsOfSvc.ToString();
		}

		public bool Equals(Employee other)
		{
			if (this.empID == other.empID)
			{
				return true;
			}
			else
			{
				return false;
			}
		}

		// Statyczna metoda pobierająca obiekt odpowiedzialny za porównywanie
		public static EmployeeComparer GetComparer()
		{
			return new Employee.EmployeeComparer();
		}


		// Obiekt Comparer deleguje operację porównywania z powrotem do klasy Employee.
		// Klasa Employee używa domyślnej metody 
		// CompareTo dla liczb całkowitych
		public int CompareTo(Employee rhs)
		{
			return this.empID.CompareTo(rhs.empID);
		}


		// Specjalna implementacja wywoływana przez niestandardowy obiekt Comparer 
		public int CompareTo(
		   Employee rhs,
		   Employee.EmployeeComparer.ComparisonType which)
		{
			switch (which)
			{
				case Employee.EmployeeComparer.ComparisonType.EmpID:
					return this.empID.CompareTo(rhs.empID);
				case Employee.EmployeeComparer.ComparisonType.Yrs:
					return this.yearsOfSvc.CompareTo(rhs.yearsOfSvc);
			}
			return 0;
		}

		// Zagnieżdżona klasa implementująca interfejs IComparer
		public class EmployeeComparer : IComparer<Employee>
		{
			// Prywatna zmienna stanu
			private Employee.EmployeeComparer.ComparisonType
			   whichComparison;

			// Wyliczenie sposobów porównywania
			public enum ComparisonType
			{
				EmpID,
				Yrs
			};

			public bool Equals(Employee lhs, Employee rhs)
			{
				return this.Compare(lhs, rhs) == 0;
			}


			public int GetHashCode(Employee e)
			{
				return e.GetHashCode();
			}

			// Nakazuje obiektem Employee, aby się porównały
			public int Compare(Employee lhs, Employee rhs)
			{
				return lhs.CompareTo(rhs, WhichComparison);
			}

			public Employee.EmployeeComparer.ComparisonType
			   WhichComparison
			{
				get { return whichComparison; }
				set { whichComparison = value; }
			}

		}
	}
	public class Tester
	{
		static void Main()
		{
			List<Employee> empArray = new List<Employee>();

			// Generowanie liczb losowych zarówno
			// dla liczb całkowitych, jak i dla 
			// identyfikatorów pracowników
			Random r = new Random();

			// Zapełnianie tablicy 
			for (int i = 0; i < 5; i++)
			{
				// Dodawanie losowego identyfikatora pracownika

				empArray.Add(
				   new Employee(
					  r.Next(10) + 100, r.Next(20)
				   )
				);
			}

			// Wyświetla całą zawartość tablicy obiektów klasy Employee 
			for (int i = 0; i < empArray.Count; i++)
			{
				Console.Write("\n{0} ", empArray[i].ToString());
			}
			Console.WriteLine("\n");


			// Sortuje i wyświetla tablicę obiektów klasy Employee
			Employee.EmployeeComparer c = Employee.GetComparer();
			c.WhichComparison =
			   Employee.EmployeeComparer.ComparisonType.EmpID;
			empArray.Sort(c);

			// Wyświetlanie całej zawartości tablicy obiektów klasy Employee
			for (int i = 0; i < empArray.Count; i++)
			{
				Console.Write("\n{0} ", empArray[i].ToString());
			}
			Console.WriteLine("\n");


			c.WhichComparison = Employee.EmployeeComparer.ComparisonType.Yrs;
			empArray.Sort(c);

			for (int i = 0; i < empArray.Count; i++)
			{
				Console.Write("\n{0} ", empArray[i].ToString());
			}
			Console.WriteLine("\n");

		}
	}
}
