using System; using System.Collections.ObjectModel; using System.Threading.Tasks; using System.Threading; using System.Linq; using Xamarin.Forms; using Grpc.Core; using Aurora.Services; using Aurora.Proto.General; using Aurora.Proto.Party; using Aurora.Proto.Playback; using Aurora.Proto.Events; using Aurora.Services.ClientService; namespace Aurora.Design.Views.Party { enum PartyState { SelectingHost, InParty, Connecting, } public class PartyViewModel : BaseViewModel { private PartyState _state; private string _hostname; private ObservableCollection _members; public PartyViewModel() { this.JoinCommand = new Command(OnJoinExecute, CanJoinExecute); this.HostCommand = new Command(OnHostExecute, CanHostExecute); _members = new ObservableCollection(); SetState(PartyState.SelectingHost); //Hook up event handler ClientService.Instance.EventReceived += this.OnEventReceived; } ~PartyViewModel() { //Task.Run(ServerService.Instance.Stop); } #region Properties public ObservableCollection Members { get { return _members; } set { SetProperty(ref _members, value); } } public bool IsSelectingHost { get { return _state == PartyState.SelectingHost; } } public bool IsNotSelectingHost { get { return _state != PartyState.SelectingHost; } } public Command JoinCommand { get; set; } public Command HostCommand { get; set; } public string Hostname { get { return _hostname; } set { SetProperty(ref _hostname, value); } } #endregion Properties #region Events /// /// An event handler for the client receiving update events /// /// The object that sent the event /// The event arguments public void OnEventReceived(object sender, EventReceivedEventArgs eventArgs) { switch (eventArgs.BaseEvent.DerivedEventCase) { case BaseEvent.DerivedEventOneofCase.None: { throw new InvalidOperationException(); } case BaseEvent.DerivedEventOneofCase.PartyMemberJoinedEvent: { PartyMemberJoinedEvent derivedEvent = eventArgs.BaseEvent.PartyMemberJoinedEvent; PartyMember member = new PartyMember { UserName = derivedEvent.Member.UserName, Id = derivedEvent.Member.Id, IpAddress = derivedEvent.Member.IpAddress, Port = derivedEvent.Member.Port }; AddMember(member); break; } case BaseEvent.DerivedEventOneofCase.PartyMemberLeftEvent: { PartyMemberJoinedEvent derivedEvent = eventArgs.BaseEvent.PartyMemberJoinedEvent; var found = Members.Where(x => x.Id == derivedEvent.Member.Id); foreach (PartyMember member in found) { _members.Remove(member); } break; } } } #endregion Events #region Commands private async void OnJoinExecute() { ClientService.Instance.Start(Hostname, SettingsService.Instance.DefaultPort.ToString()); await JoinParty(); SetState(PartyState.Connecting); } private bool CanJoinExecute() { return true; } private async void OnHostExecute() { ServerService.Instance.Start(); string localHost = ServerService.GetLocalIPAddress(); ClientService.Instance.Start(localHost, SettingsService.Instance.DefaultPort.ToString()); await JoinParty(); ClientService.Instance.GetEvents(); //Change state SetState(PartyState.Connecting); } private bool CanHostExecute() { return true; } #endregion Commands #region Private Methods /// /// Join the remote party. /// /// private async Task JoinParty() { try { JoinPartyResponse resp = await ClientService.Instance.RemotePartyClient.JoinPartyAsync(new JoinPartyRequest { UserName = SettingsService.Instance.Username, }); SettingsService.Instance.ClientId = resp.ClientId; RefreshMembers(); //Subscribe to events SubscribeRequest req = new SubscribeRequest(); req.EventTypes.Add(EventType.PartyMemberJoined); req.EventTypes.Add(EventType.PartyMemberLeft); if (!string.IsNullOrWhiteSpace(SettingsService.Instance.ClientId)) { req.ClientId = SettingsService.Instance.ClientId; } Console.WriteLine(string.Format("CLIENT {0} - SubscribeToEvents called from client with id", SettingsService.Instance.ClientId)); ClientService.Instance.RemoteEventClient.SubscribeToEvents(req); } catch (Exception ex) { Console.WriteLine("Error subscribing to events: " + ex.Message); } } /// /// Refresh members list. /// private void RefreshMembers() { MembersResponse response = ClientService.Instance.RemotePartyClient.GetPartyMembers(new Empty()); //Add members foreach (PartyMember member in response.Members) { Members.Add(member); } } private void SetState(PartyState state) { _state = state; OnPropertyChanged("IsSelectingHost"); OnPropertyChanged("IsNotSelectingHost"); } private void AddMember(PartyMember member) { Members.Add(member); } #endregion Private Methods } }