using System;
using System.Collections.Generic;

namespace Replikanto
{
	public class BijectiveDictionary<TFirst, TSecond>
	{
		public void Add(TFirst first, TSecond second)
		{
			if (this.idictionary_0.ContainsKey(first) || this.idictionary_1.ContainsKey(second))
			{
				throw new ArgumentException("Duplicate first or second");
			}
			this.idictionary_0.Add(first, second);
			this.idictionary_1.Add(second, first);
		}

		public TSecond GetByFirst(TFirst first)
		{
			TSecond tsecond;
			if (!this.idictionary_0.TryGetValue(first, out tsecond))
			{
				throw new ArgumentException("first");
			}
			return tsecond;
		}

		public TFirst GetBySecond(TSecond second)
		{
			TFirst tfirst;
			if (!this.idictionary_1.TryGetValue(second, out tfirst))
			{
				throw new ArgumentException("second");
			}
			return tfirst;
		}

		public void RemoveByFirst(TFirst first)
		{
			TSecond tsecond;
			if (!this.idictionary_0.TryGetValue(first, out tsecond))
			{
				throw new ArgumentException("first");
			}
			this.idictionary_0.Remove(first);
			this.idictionary_1.Remove(tsecond);
		}

		public void RemoveBySecond(TSecond second)
		{
			TFirst tfirst;
			if (!this.idictionary_1.TryGetValue(second, out tfirst))
			{
				throw new ArgumentException("second");
			}
			this.idictionary_1.Remove(second);
			this.idictionary_0.Remove(tfirst);
		}

		public bool TryAdd(TFirst first, TSecond second)
		{
			if (!this.idictionary_0.ContainsKey(first) && !this.idictionary_1.ContainsKey(second))
			{
				this.idictionary_0.Add(first, second);
				this.idictionary_1.Add(second, first);
				return true;
			}
			return false;
		}

		public bool TryGetByFirst(TFirst first, out TSecond second)
		{
			return this.idictionary_0.TryGetValue(first, out second);
		}

		public bool TryGetBySecond(TSecond second, out TFirst first)
		{
			return this.idictionary_1.TryGetValue(second, out first);
		}

		public bool TryRemoveByFirst(TFirst first)
		{
			TSecond tsecond;
			if (!this.idictionary_0.TryGetValue(first, out tsecond))
			{
				return false;
			}
			this.idictionary_0.Remove(first);
			this.idictionary_1.Remove(tsecond);
			return true;
		}

		public bool TryRemoveBySecond(TSecond second)
		{
			TFirst tfirst;
			if (!this.idictionary_1.TryGetValue(second, out tfirst))
			{
				return false;
			}
			this.idictionary_1.Remove(second);
			this.idictionary_0.Remove(tfirst);
			return true;
		}

		public int Count
		{
			get
			{
				return this.idictionary_0.Count;
			}
		}

		public void Clear()
		{
			this.idictionary_0.Clear();
			this.idictionary_1.Clear();
		}

		internal static bool smethod_0()
		{
			return BijectiveDictionary<TFirst, TSecond>.object_0 == null;
		}

		internal static object smethod_1()
		{
			return BijectiveDictionary<TFirst, TSecond>.object_0;
		}

		private IDictionary<TFirst, TSecond> idictionary_0 = new Dictionary<TFirst, TSecond>();

		private IDictionary<TSecond, TFirst> idictionary_1 = new Dictionary<TSecond, TFirst>();

		private static object object_0;
	}
}
