using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ZenFulcrum.EmbeddedBrowser
{
///
/// A class that wraps a pending promise with it's predicate and time data
///
internal class PredicateWait
{
///
/// Predicate for resolving the promise
///
public Func predicate;
///
/// The time the promise was started
///
public float timeStarted;
///
/// The pending promise which is an interface for a promise that can be rejected or resolved.
///
public IPendingPromise pendingPromise;
///
/// The time data specific to this pending promise. Includes elapsed time and delta time.
///
public TimeData timeData;
}
///
/// Time data specific to a particular pending promise.
///
public struct TimeData
{
///
/// The amount of time that has elapsed since the pending promise started running
///
public float elapsedTime;
///
/// The amount of time since the last time the pending promise was updated.
///
public float deltaTime;
}
public interface IPromiseTimer
{
///
/// Resolve the returned promise once the time has elapsed
///
IPromise WaitFor(float seconds);
///
/// Resolve the returned promise once the predicate evaluates to true
///
IPromise WaitUntil(Func predicate);
///
/// Resolve the returned promise once the predicate evaluates to false
///
IPromise WaitWhile(Func predicate);
///
/// Update all pending promises. Must be called for the promises to progress and resolve at all.
///
void Update(float deltaTime);
}
public class PromiseTimer : IPromiseTimer
{
///
/// The current running total for time that this PromiseTimer has run for
///
private float curTime;
///
/// Currently pending promises
///
private List waiting = new List();
///
/// Resolve the returned promise once the time has elapsed
///
public IPromise WaitFor(float seconds)
{
return WaitUntil(t => t.elapsedTime >= seconds);
}
///
/// Resolve the returned promise once the predicate evaluates to false
///
public IPromise WaitWhile(Func predicate)
{
return WaitUntil(t => !predicate(t));
}
///
/// Resolve the returned promise once the predicate evalutes to true
///
public IPromise WaitUntil(Func predicate)
{
var promise = new Promise();
var wait = new PredicateWait()
{
timeStarted = curTime,
pendingPromise = promise,
timeData = new TimeData(),
predicate = predicate
};
waiting.Add(wait);
return promise;
}
///
/// Update all pending promises. Must be called for the promises to progress and resolve at all.
///
public void Update(float deltaTime)
{
curTime += deltaTime;
int i = 0;
while (i < waiting.Count)
{
var wait = waiting[i];
var newElapsedTime = curTime - wait.timeStarted;
wait.timeData.deltaTime = newElapsedTime - wait.timeData.elapsedTime;
wait.timeData.elapsedTime = newElapsedTime;
bool result;
try
{
result = wait.predicate(wait.timeData);
}
catch (Exception ex)
{
wait.pendingPromise.Reject(ex);
waiting.RemoveAt(i);
continue;
}
if (result)
{
wait.pendingPromise.Resolve();
waiting.RemoveAt(i);
}
else
{
i++;
}
}
}
}
}