using System;

namespace DataAccess.Domain.EntityBase {
	public abstract class SingleKeyEntity<TId> {
		public virtual TId Id {
			get;
			set;
		}

		/*
		/// <summary>
		/// optimistic and pessimistic concurrency to handle concurrent updates and versioning issues.
		/// </summary>
		public virtual int Version {
			get;
			set;
		}*/

		public override bool Equals(object obj) {
			return Equals(obj as SingleKeyEntity<TId>);
		}

		private static bool IsTransient(SingleKeyEntity<TId> obj) {
			return obj != null && Equals(obj.Id, default(TId));
		}

		private Type GetUnproxiedType() {
			return GetType();
		}

		public virtual bool Equals(SingleKeyEntity<TId> other) {
			if (other == null) {
				return false;
			}

			if (ReferenceEquals(this, other)) {
				return true;
			}

			if (!IsTransient(this) && !IsTransient(other) && Equals(Id, other.Id)) {
				var otherType = other.GetUnproxiedType();
				var thisType = GetUnproxiedType();
				return thisType.IsAssignableFrom(otherType) || otherType.IsAssignableFrom(thisType);
			}

			return false;
		}

		public override int GetHashCode() {
			if (Equals(Id, default(TId))) {
				return base.GetHashCode();
			}
			return Id.GetHashCode();
		}
	}
}
