using System;
using System.Diagnostics.Tracing;
using System.Threading;

namespace EventCountersDemo
{
	class Program
	{
		static void Main(string[] args)
		{
			Console.WriteLine($"dotnet counters monitor -p {Environment.ProcessId} --counters System.Runtime {JiriEventSource.Instance.Name}");
			var random = new Random();
			while (true)
			{
				JiriEventSource.Instance.Event(random.Next(0, 10));
				JiriEventSource.Instance.Increment(1);
				JiriEventSource.Instance.IncrementPolling();
				Console.ReadLine();
			}
		}
	}

	[EventSource(Name = "Jiri.EventSource")]
	public sealed class JiriEventSource : EventSource
	{
		public static JiriEventSource Instance { get; } = new JiriEventSource();

		EventCounter _eventCounter;
		IncrementingEventCounter _incrementingEventCounter;
		IncrementingPollingCounter _incrementingPollingEventCounter;
		PollingCounter _pollingEventCounter;

		long _value;

		JiriEventSource()
		{
			_eventCounter = new EventCounter("event-counter", this)
			{
				DisplayName = "Event Counter",
				DisplayUnits = "units",
			};
			_incrementingEventCounter = new IncrementingEventCounter("incrementing-event-counter", this)
			{
				DisplayName = "Incrementing Event Counter",
				DisplayUnits = "units",
				DisplayRateTimeScale = TimeSpan.FromSeconds(10),
			};
			_incrementingPollingEventCounter = new IncrementingPollingCounter("incrementing-polling-event-counter", this, () => Volatile.Read(ref _value))
			{
				DisplayName = "Incrementing Polling Event Counter",
				DisplayUnits = "units",
				DisplayRateTimeScale = TimeSpan.FromSeconds(10),
			};
			_pollingEventCounter = new PollingCounter("polling-event-counter", this, () => Math.PI)
			{
				DisplayName = "Polling Event Counter",
				DisplayUnits = "units",
			};
		}

		protected override void OnEventCommand(EventCommandEventArgs command)
		{
			//if (command.Command == EventCommand.Enable)
			//{

			//}

			base.OnEventCommand(command);
		}

		//[Event(1, Level = EventLevel.Informational, Message = "Foo")]
		public void Event(int value)
		{
			WriteEvent(1, value);
			_eventCounter.WriteMetric(value);
		}

		public void Increment(int value)
		{
			WriteEvent(2, value);
			_incrementingEventCounter.Increment(value);
		}

		public void IncrementPolling()
		{
			Interlocked.Increment(ref _value);
		}

		protected override void Dispose(bool disposing)
		{
			_pollingEventCounter.Dispose();
			_incrementingPollingEventCounter.Dispose();
			_incrementingEventCounter.Dispose();
			_eventCounter.Dispose();

			base.Dispose(disposing);
		}
	}
}
