private Reachability Change(UniqueAddress observer, UniqueAddress subject, ReachabilityStatus status)
{
var v = NextVersion(observer);
var newVersions = _versions.SetItem(observer, v);
var newRecord = new Record(observer, subject, status, v);
var oldObserverRows = ObserverRows(observer);
if (oldObserverRows == null && status == ReachabilityStatus.Reachable) return this;
if (oldObserverRows == null) return new Reachability(_records.Add(newRecord), newVersions);
Record oldRecord = null;
oldObserverRows.TryGetValue(subject, out oldRecord);
if (oldRecord == null)
{
if (status == ReachabilityStatus.Reachable &&
oldObserverRows.Values.All(r => r.Status == ReachabilityStatus.Reachable))
{
return new Reachability(_records.FindAll(r => !r.Observer.Equals(observer)), newVersions);
}
return new Reachability(_records.Add(newRecord), newVersions);
}
if (oldRecord.Status == ReachabilityStatus.Terminated || oldRecord.Status == status)
return this;
if(status == ReachabilityStatus.Reachable &&
oldObserverRows.Values.All(r => r.Status == ReachabilityStatus.Reachable || r.Subject.Equals(subject)))
return new Reachability(_records.FindAll(r => !r.Observer.Equals(observer)), newVersions);
var newRecords = _records.SetItem(_records.IndexOf(oldRecord), newRecord);
return new Reachability(newRecords, newVersions);
}