IDictionary<string, string> GetProperties(EventMetadata metadata)
		{
			var result = new Dictionary<string, string>();
			var properties = metadata.Metadata?.Properties;

			foreach (var property in properties) {
				var name = property.Name;
				var value = property.Value;

				var type = property.Type == null ? null : Type.GetType(property.Type, throwOnError: false, ignoreCase: true);

				if (string.IsNullOrEmpty (value) && type == null) {
					continue;
				}

				if (string.IsNullOrEmpty(value)) {
					value = GetValue (type, property.Range);
				}

				if (value.Contains ("|")) {
					var options = value.Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries);

					value = options[random.Next (0, options.Count () - 1)].Trim();
				}

				result.Add (name, value);
			}

			return result;
		}
		IEnumerable<Event> GetEvents(EventMetadata metadata)
		{
			var events = new List<Event>();

			for(var i = 1; i <= metadata.Count; i++) {
				events.Add (GetEvent (metadata));
			}

			return events;
		}
		Event GetEvent(EventMetadata metadata)
		{
			var ev = new Event
			{
				Name = metadata.EventName
			};
			var properties = GetProperties(metadata);
			var metrics = GetMetrics(metadata);

			foreach(var property in properties) {
				ev.Properties.Add (property);
			}

			foreach (var metric in metrics) {
				ev.Metrics.Add (metric);
			}

			return ev;
		}
		IDictionary<string, double> GetMetrics(EventMetadata metadata)
		{
			var result = new Dictionary<string, double>();
			var metrics = metadata.Metadata?.Metrics;

			foreach(var metric in metrics) {
				var name = string.Format("{0}.{1}", metadata.EventName, metric.Name);
				var value = metric.Value;

				if(value < 1) {
					value = metric.Range == null ?
					random.NextDouble () :
					random.Next (metric.Range.MinValue, metric.Range.MaxValue);
				}

				result.Add (name, value);
			}

			return result;
		}