using System;
using System.Collections.Generic;
using System.IO;
using System.ServiceModel;
using System.ComponentModel.Composition;
using WindowsPhone.Recipes.Push.Server.Models;
using System.Xml.Linq;
namespace WindowsPhone.Recipes.Push.Server.Services
{
///
/// Current push server services implementation.
///
[Export, PartCreationPolicy(CreationPolicy.Shared), ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
internal class PushService : IPushService
{
#region Fields
private ServiceHost _serviceHost;
/// Dictionary contains users subscription objects.
private readonly Dictionary _subscribers = new Dictionary();
/// Sync access to the subscribers dictionary.
private readonly object SubscribersSync = new object();
#endregion
#region Events
///
/// Raise when user subscribed.
///
public event EventHandler Subscribed;
///
/// Raise when current server status is requested.
///
public event EventHandler GetInfo;
///
/// Raise when user requests a tile update.
///
public event EventHandler TileUpdateRequest;
#endregion
#region Properties
///
/// Get subscription list.
///
public IEnumerable Subscribers
{
get
{
lock (_subscribers)
{
var subscribers = new Subscription[_subscribers.Count];
_subscribers.Values.CopyTo(subscribers, 0);
return subscribers;
}
}
}
///
/// Get subscription count.
///
public int SubscribersCount
{
get
{
lock (_subscribers)
{
return _subscribers.Count;
}
}
}
#endregion
#region Operations
///
/// Register user with notification channel uri.
///
/// The user name to register.
/// The notification channel uri.
public void Register(string userName, Uri channelUri)
{
if (string.IsNullOrEmpty(userName))
{
throw new ArgumentException("Invalid user name", "userName");
}
if (channelUri == null)
{
throw new ArgumentNullException("channelUri");
}
var subscription = new Subscription(userName, channelUri);
lock (SubscribersSync)
{
// Add or update existing.
_subscribers[userName] = subscription;
}
OnSubscribed(new SubscriptionEventArgs(subscription));
}
///
/// Gets current server info.
///
/// An instance info object contains server status.
public ServerInfo GetServerInfo()
{
var args = new ServerInfoEventArgs();
OnGetInfo(args);
return args.ServerInfo;
}
///
/// Send a tile update with given parameter.
///
/// An instance info object contains server status.
/// User parameter to send with the tile update request.
public void UpdateTile(Uri channelUri, string parameter)
{
OnTileUpdateRequest(new TileUpdateRequestEventArgs(channelUri, parameter));
}
internal Subscription TryGetSubscription(string userName)
{
lock (SubscribersSync)
{
Subscription subscription;
if (!_subscribers.TryGetValue(userName, out subscription))
{
subscription = null;
}
return subscription;
}
}
#endregion
#region Privates Logic
public void Host()
{
_serviceHost = new ServiceHost(this);
_serviceHost.Open();
}
private void OnSubscribed(SubscriptionEventArgs args)
{
if (Subscribed != null)
{
Subscribed(this, args);
}
}
private void OnGetInfo(ServerInfoEventArgs args)
{
if (GetInfo != null)
{
GetInfo(this, args);
}
}
private void OnTileUpdateRequest(TileUpdateRequestEventArgs args)
{
if (TileUpdateRequest != null)
{
TileUpdateRequest(this, args);
}
}
#endregion
}
}