public UserViewModel(Profile profile)
 {
     _profile = profile;
     Name = profile.FirstName + " " + profile.LastName;
     Description = string.Format("{0}, {1} years old, {2}",
         profile.Gender.ToString(), profile.Age, CountriesRepository.Get(profile.LocaleID));
 }
		public UserDetailViewModel(ApplicationManager appManager, Profile profile)
        {
			_appManager = appManager;

			//Auto map it like it's hot
			//Copy, flatten, you can make it happen
			AutoMapper.CopyPropertyValues (profile, this);
			AutoMapper.CopyPropertyValues (profile.Details, this);
        }
		private async void OnViewProfile()
		{
			var profile = new Profile ();
			profile.Details = new ProfileDetails ();
			AutoMapper.CopyPropertyValues (_appManager.AccountManager.CurrentUser, profile);
			AutoMapper.CopyPropertyValues (_appManager.AccountManager.CurrentUser, profile.Details);

			var model = new UserDetailViewModel (_appManager, profile) {
				HasChatOption = false
			};
			await model.ShowAsync ();
		}
        /// <summary>
        /// This is the first step of a logged in user for chatting.
        /// </summary>
        public async Task ReloadUsers()
        {
			ConnectedMembersResponse chatStatus;

			chatStatus = await _chatServiceProxy.GetConnectedMembers(new ConnectedMembersRequest()
				{
					SSID = _accountManager.SSID,
					PracticingLanguages = _accountManager.CurrentUser.PracticingLanguages,
					KnownLanguages = _accountManager.CurrentUser.KnownLanguages,
					LocaleID = _accountManager.CurrentUser.LocaleID,
					Age = _accountManager.CurrentUser.Age,
					Gender = _accountManager.CurrentUser.Gender,
					LastName = _accountManager.CurrentUser.LastName,
					FirstName = _accountManager.CurrentUser.FirstName,
					UserID = _accountManager.CurrentUser.UserId
				});

            OnlineUsers.Clear();

			if (chatStatus == null)
			{
				return;
			}
            
			_sessionGuid = chatStatus.GUID;

			_updateBuilder.Instantiate(_accountManager.CurrentUser.UserId,_sessionGuid);
			_updateBuilder.NewRequest (0, UpdateObjectsReceivedCount, CurrentUpdateRequestCount);

			foreach (var user in chatStatus.Users)
			{
				Profile userProfile = new Profile ();
				AutoMapper.CopyPropertyValues (user, userProfile);
				OnlineUsers.Add(userProfile);
				if (!UserDirectory.ContainsKey (userProfile.UserId)) 
				{
					UserDirectory.Add (userProfile.UserId, userProfile);
				} 
				else 
				{
					UserDirectory [userProfile.UserId] = userProfile;
				}
			}

			//Get our first update immediately, then start spinning
			await GetChatUpdate ();
			SpinOnChatUpdate ();
        }
		public async Task GetChatUpdate()
		{
			if (_sessionGuid != null && _accountManager.IsLoggedIn)
			{
				_lastUpdateTime = DateTime.Now;

				//This might be slightly smarter if the timer was closer to the request, but this approximation on the 
				//response time should be close enough for the server
				System.Diagnostics.Stopwatch timer = new Stopwatch();
				timer.Start();

				//Send a chat update request
				ChatUpdateResponse chatStatus = await _chatServiceProxy.GetChatUpdate (_updateBuilder.ToRequest ());

				if (chatStatus == null)
				{
					return;
				}

				timer.Stop();
				//HACK: Time is way off, making it more realistic till i figure out how to improve accuracy
				TimeSpan responseTime = timer.Elapsed - TimeSpan.FromMilliseconds(130);

				//Client update count increments by one every time we send a request
				CurrentUpdateRequestCount++;

				//Do some quick checks to make sure we are still logged in and ready for a message
				if (_sessionGuid != null && _accountManager.IsLoggedIn && _updateBuilder != null && chatStatus != null)
				{
					//Every update, we refresh all our typing events
					Rooms.ClearAllTypingEvents ();

					//Clear out our update buffer and increment our packet id's

					//Update our received count by the count in the response
					UpdateObjectsReceivedCount += chatStatus.Updates.Count;

					//Clear out our buffer so we can start a new update request
					_updateBuilder.NewRequest (Math.Abs(responseTime.TotalMilliseconds), UpdateObjectsReceivedCount, CurrentUpdateRequestCount);

					//Consume the response
					LastServerUpdateId = chatStatus.ServerUpdateId;
					foreach (var update in chatStatus.Updates)
					{
						//Parse the update type
						if (update.User != null)
						{
							Profile userProfile = new Profile ();
							AutoMapper.CopyPropertyValues (update.User, userProfile);
							if (!OnlineUsers.Any (p => p.UserId == userProfile.UserId))
							{
								OnlineUsers.Add (userProfile);
							}
							//Else update?
							if (!UserDirectory.ContainsKey (userProfile.UserId))
							{
								UserDirectory.Add (userProfile.UserId, userProfile);
							}
							//Else update?
						}
						else if (update.DisconnectedUser != null)
						{
							//The server sends two things with this update, either the user disconnected from a 
							//room, or disconnected entirely from the server.
							if (update.DisconnectedUser.RoomId != null)
							{
								if (Rooms.ContainsKey(update.DisconnectedUser.RoomId) && RoomFactory.IsUserRoom (update.DisconnectedUser.RoomId))
								{
									Rooms.SetStatus (update.DisconnectedUser.RoomId, RoomStatus.OtherUserLeft);
							
								}
							}
							else
							{
								//Should we remove these users from the directory too?
								OnlineUsers.RemoveAll (t => t.UserId == update.DisconnectedUser.UserId);
							}
						}
						else if (update.FP != null)
						{
							var fp = update.FP;
							//The server can send us duplicate typing events, only add one
							if (Rooms.ContainsKey(fp.Room) && !Rooms [fp.Room].TypingEvents.Any (t => (t as TypingEvent).UserId == fp.UserId))
							{
								Rooms.AddTypingEvent (fp.Room, new TypingEvent () {
									UserName = GetUserFirstName (fp.UserId),
									UserId = fp.UserId
								});
							}
						}
						else if (update.Message != null)
						{
							var message = update.Message;
							var room = message.Room;

							//group the same user's last chats together
							//var lastMessage = Rooms.LastTextMessage (room) as TextMessage;
							//TODO: Fix the bug with grouping chats duplication
							//if (lastMessage != null && lastMessage.UserId == message.UserId)
//							{
//								Rooms.RemoveTextMessage (room, lastMessage);
//								lastMessage.Body += "\n\n" + message.Text;
//								lastMessage.Timestamp = DateTime.Now;
//								Rooms.AddTextMessage (room, lastMessage);
//							}
//							else
							if(Rooms.ContainsKey(room))
							{
								//BUG: Sometimes we are getting some users that whose names we aren't sure about...
								//Need to investigate this.
								var messageUsername = GetUserFirstName (message.UserId);
								Rooms.AddTextMessage (room, new TextMessage () {
									UserName = messageUsername,
									Body = message.Text,
									UserId = message.UserId,
									Timestamp = DateTime.Now
								});
							}
						}
						else if (update.EnteredRoom != null)
						{
							var enteredRoom = update.EnteredRoom;
							var room = update.EnteredRoom.Room;

							if(Rooms.ContainsKey(room))
							{
								Rooms.SetStatus (room, RoomStatus.Connected);
								Rooms.AddTextMessageRange (room, enteredRoom.RoomMessages.Select (r =>
									new TextMessage () {
									UserName = r.User.Name.Replace("·","").Trim(),  //strip weird appends from the server
									Body = r.Message.Body,
									UserId = null, //How can we get this?  only the first name is sent, so we can't resolve duplicate names
									Timestamp = DateTime.Now
								}));
							}
											
						}
						else if (update.UserChatRequest != null)
						{
							var request = update.UserChatRequest;

							var roomId = RoomFactory.GetRoomId (request.UserId, _accountManager.CurrentUser.UserId);
							//do something
							if (!Rooms.ContainsKey (roomId))
							{
								Rooms.CreateRoom (new Room(roomId, GetUserFullName(request.UserId)){ UserId = request.UserId });
							}
							Rooms.SetStatus (roomId, RoomStatus.AwaitingOurApproval);
						}
						else if (update.UserChatResult != null)
						{
							var chatResult = update.UserChatResult;
							if (!UserDirectory.ContainsKey (chatResult.UserId))
							{
								//If for some reason we got a chat result from a user that isn't connected,
								//I think we should just ignore it
								break;
							}

							var roomId = RoomFactory.GetRoomId(_accountManager.CurrentUser.UserId, chatResult.UserId);

							switch (chatResult.Reply)
							{
							case ChatReply.Ok:
								{
									_updateBuilder.AddAcceptedUserRoom (roomId);


									//So, we can be getting responses from a different session.  In that case,
									//we will need to spawn up a room and act as if we always intended to get
									//this chat accpetance
									if (!Rooms.ContainsKey (roomId))
									{
										Rooms.CreateRoom (new Room(roomId, GetUserFullName(chatResult.UserId)){ UserId = chatResult.UserId });
									}

									Rooms.SetStatus (roomId, RoomStatus.Connected);
								}
								break;
							case ChatReply.No:
								Rooms.SetStatus (roomId, RoomStatus.OtherUserDeclined);
								break;
							default:
								throw new NotSupportedException ("Chat reply is not known");
							}
						}
						else
						{
							throw new InvalidOperationException ("An update was sent with no parameter");
						}
					}

				}
			}
			
		}