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

using glue.Collections.XSpinLock;
using glue.Tasks;
using glue.Extensions.Enumerable;
using glue.Tokenization;
using agree.Parse;

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// 
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public partial class TestChart : UnificationParseChart<TestEdge>
{

	public TestChart(agree.ISysObj so_owner, TokenizedString ts, IEnumerable<TestGrammarRule> rules, IEnumerable<IParseChartEdge> sentence)
		: base(new ParserConfiguration(), so_owner, "desc", Program.start_sym, ts.MinimalSpanCount, sentence)
	{
		this.rules = rules.Where(r => r.RuleDaughters().Count <= ColumnCount).ToArray();
	}
	readonly IGrammarRule[] rules;

	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <summary>
	/// Generate new activities for the specified ChartEdge
	/// Match the given chart edge against this chart's set of rules, and generate new rule blocks to maintain the
	/// edge as active.
	/// </summary>
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	protected override void GenerateRules(IParseChartEdge ce)
	{
		foreach (IGrammarRule r in rules)
		{
			// if the edge doesn't fit, don't bother creating the active edge.
			if (ce.ChartSpan.EndIndex > ColumnCount - r.RuleDaughters().Count)
				continue;

			// create active chart edge
			new ActiveRightEdge(this, r, null).TryMatchEdge(ce);
		}
	}


#if false
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <summary>
	/// 
	/// </summary>
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	public static bool Unify(TfsEdge e1, TfsEdge e2, TfsEdge result)
	{
		int rv = rnd.Next(2);
		if (rv > 0)
			Thread.Sleep(rv);
		return e1.s == e2.s;
	}
#endif

	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <summary>
	/// 
	/// </summary>
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#if true
	public override bool UnifyPartial(IGrammarRule mother, TestEdge daughter, TestEdge candidate, out TestEdge result, bool f_last)
	{
		if (Program.f_unif_delay)
		{
			int rv = Program.rnd.Next(4);
			if (rv > 0)
				for (int x = 0; x < rv * 10000; x++) { }
		}

		if (daughter.s == candidate.s)
		{
			result = mother.Self;
			return true;
		}
		result = default(TestEdge);
		return false;
	}

	public override Task<TestEdge> UnifyPartialAsync(IGrammarRule mother, TestEdge daughter, TestEdge candidate, bool f_last)
	{
		if (daughter.s == candidate.s)
		{
			return Tasks.FromResult(mother.Self);
		}
		return Tasks.FromResult(default(TestEdge));
	}

#else
	public static Task<TestEdge> UnifyAsync(TestEdge e1, TestEdge e2)
	{
		TestEdge e = (e1.s == e2.s) ? new TestEdge(e1.s) : default(TestEdge);

		if (f_unif_delay)
		{
			int rv = rnd.Next(4);
			if (rv > 0)
				return TaskEx.Delay(rv).ContinueWith<TestEdge>(t => e);
		}
		return agree.Util.Tasks.Tasks.FromResult<TestEdge>(e);
	}
#endif


	public override bool CanUnify(TestEdge t1, TestEdge t2)
	{
		return t1.s == t2.s;
	}

	public override IGrammarRule IncorporatePart(IGrammarRule mother, TestEdge result)
	{
		return mother;
	}
};