using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

using miew.Debugging;

namespace agree
{
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <summary>
	/// 
	/// </summary>
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	public partial class BootstrapTfs : MarkingTfs
	{
		public BootstrapTfs(TypeMgr tm, int c_edge_hint)
			: base(tm)
		{
			this.d = new Dictionary<UInt64, Edge>(c_edge_hint | 1);
		}
		public BootstrapTfs(TypeMgr tm, Type t, bool f_coref)
			: base(tm, t, f_coref)
		{
			this.d = new Dictionary<UInt64, Edge>(277);
		}

		public Dictionary<UInt64, Edge> d;

		public override Tfs Clone() { throw new NotImplementedException(); }

		public override int EdgeCount { get { return d.Count; } }

		public override void SetEdge(int i_feat, int mark, Edge e)
		{
			Debug.Assert(mark != 0);
			Debug.Assert(!e.Equals(default(Edge)));
			d[((ulong)i_feat << 32) | (uint)mark] = e;
		}

		public override bool TryGetEdge(int i_feat, int mark, out Edge e)
		{
			Debug.Assert(mark != 0);
			return d.TryGetValue(((ulong)i_feat << 32) | (uint)mark, out e);
		}

		public override Edge.Flag TryGetFlagsMark(int i_feat, int mark, out int m)
		{
			Edge e;
			d.TryGetValue(((ulong)i_feat << 32) | (uint)mark, out e);
			m = e.Mark;
			return e.FlagsId;
		}


		public unsafe override ulong GetUlEdge(FeatMark fm)
		{
			Edge e;
			d.TryGetValue(((ulong)fm.i_feat << 32) | (uint)fm.m, out e);
			return *(ulong*)&e;
		}

		public override Edge GetEdge(int i_feat, int mark)
		{
			Debug.Assert(mark != 0);
			Edge e;
			d.TryGetValue(((ulong)i_feat << 32) | (uint)mark, out e);
			return e;
		}

		public override bool RemoveEdge(int i_feat, int mark)
		{
			Debug.Assert(mark != 0);
			return d.Remove(((ulong)i_feat << 32) | (uint)mark);
		}

		public override void AddEdge(int i_feat, int mark, Edge e)
		{
			Debug.Assert(mark != 0);
			d.Add(((ulong)i_feat << 32) | (uint)mark, e);
		}

		public override IEnumerable<FeatMarkEdge> FeatMarkEdges
		{
			get
			{
				foreach (var kvp in d)
				{
					ulong ul = kvp.Key;
					yield return new FeatMarkEdge(new FeatMark((int)(ul >> 32), (int)ul), kvp.Value);
				}
			}
		}

		public override bool ContainsFeatMark(int i_feat, int mark)
		{
			return d.ContainsKey(((ulong)i_feat << 32) | (uint)mark);
		}

		public override bool _ContainsInMark(int mark)
		{
			return d.Keys.Any(m => mark == (int)m);
		}
	};
}