/// <summary>
        /// Construct an instance from the specified tagged JSONReader stream.
        /// </summary>
        /// <param name="JSONReader">Input stream</param>
        /// <param name="Out">The created object</param>
        public static void Deserialize(JSONReader JSONReader, out JSONObject Out) {
	
			JSONReader.StartObject ();
            if (JSONReader.EOR) {
                Out = null;
                return;
                }

			string token = JSONReader.ReadToken ();
			Out = null;

			switch (token) {

				case "NetworkProfile" : {
					var Result = new NetworkProfile ();
					Result.Deserialize (JSONReader);
					Out = Result;
					break;
					}


				case "NetworkProfilePrivate" : {
					var Result = new NetworkProfilePrivate ();
					Result.Deserialize (JSONReader);
					Out = Result;
					break;
					}

				default : {
					throw new Exception ("Not supported");
					}
				}	
			JSONReader.EndObject ();
            }
        /// <summary>
        /// Generate a new profile with the requested options. Note that this could be
        /// parallelized very easily by performing time consuming operations (e.g. generating
        /// keys) while the user is answering other questions.
        /// </summary>
        public void GenerateProfile() {

            UserProfile = new PersonalProfile(ThisDevice);
            UDF = UserProfile.PersonalMasterProfile.MasterSignatureKey.UDF;

            if (ConfigurePassword) {
                var PasswordProfile = new PasswordProfile(UserProfile);
                PasswordProfile.AddDevice(ThisDevice);
                MeshClient.Publish(PasswordProfile.Signed);
                }

            if (ConfigureNetwork) {
                var NetworkProfile = new NetworkProfile(UserProfile);
                NetworkProfile.AddDevice(ThisDevice);
                MeshClient.Publish(NetworkProfile.Signed);
                }

            if (ConfigureEmail) {
                foreach (var MailAccountInfo in MailAccountInfos) {
                    // Add in the S/MIME parameters and update the profile
                    //if (!MailAccountInfo.GotSMIME) {
                        MailAccountInfo.GenerateSMIME();
                        MailAccountInfo.Update();
                        //}

                    var MailProfile = new MailProfile(UserProfile, MailAccountInfo);
                    MailProfile.AddDevice(ThisDevice);

                    //var SignedMailProfile = new SignedApplicationProfile(MailProfile);
                    MeshClient.Publish(MailProfile.Signed);
                    }
                }

            if (ConfigureRecovery) {
                MakeCheckRecovery();
                }

            // publish to the cloud
            var SignedProfile = new SignedPersonalProfile(UserProfile);
            SignedProfile.ToRegistry();

            MeshClient.CreatePersonalProfile(AccountID, SignedProfile);
            }
        /// <summary>
        /// Deserialize a tagged stream
        /// </summary>
        /// <param name="JSONReader">The input stream</param>
        /// <returns>The created object.</returns>		
        public static new NetworkProfile  FromTagged (JSONReader JSONReader) {
			NetworkProfile Out = null;

			JSONReader.StartObject ();
            if (JSONReader.EOR) {
                return null;
                }

			string token = JSONReader.ReadToken ();

			switch (token) {

				case "NetworkProfile" : {
					var Result = new NetworkProfile ();
					Result.Deserialize (JSONReader);
					Out = Result;
					break;
					}

				default : {
					//Ignore the unknown data
                    //throw new Exception ("Not supported");
                    break;
					}
				}
			JSONReader.EndObject ();

			return Out;
			}