using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Newtonsoft.Json; using Plugins.Countly.Helpers; using Plugins.Countly.Models; namespace Plugins.Countly.Services.Impls.Actual { public class UserDetailsCountlyService : IUserDetailsCountlyService { private Dictionary _customDataProperties = new Dictionary(); private readonly RequestCountlyHelper _requestCountlyHelper; private readonly ICountlyUtils _countlyUtils; public UserDetailsCountlyService(RequestCountlyHelper requestCountlyHelper, ICountlyUtils countlyUtils) { _requestCountlyHelper = requestCountlyHelper; _countlyUtils = countlyUtils; } /// /// Modifies all user data. Custom data should be json string. /// Deletes an already defined custom property from the Countly server, if it is supplied with a NULL value /// /// /// public async Task UserDetailsAsync(CountlyUserDetailsModel userDetails) { if (userDetails == null) { return new CountlyResponse { IsSuccess = false, ErrorMessage = "No data found." }; } return await SetUserDetailsAsync(userDetails); } /// /// Modifies custom user data only. Custom data should be json string. /// Deletes an already defined custom property from the Countly server, if it is supplied with a NULL value /// /// /// public async Task UserCustomDetailsAsync(CountlyUserDetailsModel userDetails) { if (userDetails == null) { return new CountlyResponse { IsSuccess = false, ErrorMessage = "No data found." }; } return await SetCustomUserDetailsAsync(userDetails); } /// /// Uploads all user details /// /// public async Task SetUserDetailsAsync(CountlyUserDetailsModel userDetailsModel) { if (!_countlyUtils.IsPictureValid(userDetailsModel.PictureUrl)) throw new Exception("Accepted picture formats are .png, .gif and .jpeg"); var requestParams = new Dictionary { { "user_details", JsonConvert.SerializeObject(userDetailsModel, Formatting.Indented, new JsonSerializerSettings{ NullValueHandling = NullValueHandling.Ignore }) }, }; return await _requestCountlyHelper.GetResponseAsync(requestParams); } /// /// Uploads only custom data. Doesn't update any other property except Custom Data. /// /// public async Task SetCustomUserDetailsAsync(CountlyUserDetailsModel userDetailsModel) { var requestParams = new Dictionary { { "user_details", JsonConvert.SerializeObject( new Dictionary { { "custom", userDetailsModel.Custom } }) } }; return await _requestCountlyHelper.GetResponseAsync(requestParams); } /// /// Saves all custom user data updates done since the last save request. /// /// public async Task SaveAsync() { if (!_customDataProperties.Any()) { return new CountlyResponse { IsSuccess = false, ErrorMessage = "No data to save." }; } var model = new CountlyUserDetailsModel(_customDataProperties); _customDataProperties = new Dictionary { }; return await SetCustomUserDetailsAsync(model); } /// /// Sets value to key. /// Doesn't report it to the server until save is called. /// /// /// public void Set(string key, string value) { AddToCustomData(key, value); } /// /// Sets value to key, only if property was not defined before for this user. /// Doesn't report it to the server until save is called. /// /// /// public void SetOnce(string key, string value) { AddToCustomData(key, new Dictionary { { "$setOnce", value } }); } /// /// To increment value, for the specified key, on the server by 1. /// Doesn't report it to the server until save is called. /// /// public void Increment(string key) { AddToCustomData(key, new Dictionary { { "$inc", 1 } }); } /// /// To increment value on server by provided value (if no value on server, assumes it is 0). /// Doesn't report it to the server until save is called. /// /// /// public void IncrementBy(string key, double value) { AddToCustomData(key, new Dictionary { { "$inc", value } }); } /// /// To multiply value on server by provided value (if no value on server, assumes it is 0). /// Doesn't report it to the server until save is called. /// /// /// public void Multiply(string key, double value) { AddToCustomData(key, new Dictionary { { "$mul", value } }); } /// /// To store maximal value from the one on server and provided value (if no value on server, uses provided value). /// Doesn't report it to the server until save is called. /// /// /// public void Max(string key, double value) { AddToCustomData(key, new Dictionary { { "$max", value } }); } /// /// To store minimal value from the one on server and provided value (if no value on server, uses provided value). /// Doesn't report it to the server until save is called. /// /// /// public void Min(string key, double value) { AddToCustomData(key, new Dictionary { { "$min", value } }); } /// /// Add one or many values to array property (can have multiple same values, if property is not array, converts it to array). /// Doesn't report it to the server until save is called. /// /// /// public void Push(string key, string[] value) { AddToCustomData(key, new Dictionary { { "$push", value } }); } /// /// Add one or many values to array property (will only store unique values in array, if property is not array, converts it to array). /// Doesn't report it to the server until save is called. /// /// /// public void PushUnique(string key, string[] value) { AddToCustomData(key, new Dictionary { { "$addToSet", value } }); } /// /// Remove one or many values from array property (only removes value from array properties). /// Doesn't report it to the server until save is called. /// /// /// public void Pull(string key, string[] value) { AddToCustomData(key, new Dictionary { { "$pull", value } }); } public void AddToCustomData(string key, object value) { if (_customDataProperties.ContainsKey(key)) { var item = _customDataProperties.Select(x => x.Key).FirstOrDefault(x => x.Equals(key, StringComparison.OrdinalIgnoreCase)); if (item != null) { _customDataProperties.Remove(item); } } _customDataProperties.Add(key, value); } } }