<commit_before>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Ledger.Infrastructure;

namespace Ledger
{
	public class AggregateRoot<TKey>
	{
		public TKey ID { get; protected set; }
		protected internal DateTime Stamp { get; set; }
		protected internal int Sequence { get; set; }

		private readonly Func<DateTime> _getTimestamp;
		private readonly LightweightCache<Type, List<Action<DomainEvent<TKey>>>> _handlers;
		private readonly List<DomainEvent<TKey>> _events;

		protected AggregateRoot()
			: this(DefaultStamper.Now)
		{
		}

		protected AggregateRoot(Func<DateTime> getTimestamp)
		{
			_getTimestamp = getTimestamp;
			_handlers = new LightweightCache<Type, List<Action<DomainEvent<TKey>>>>(
				key => new List<Action<DomainEvent<TKey>>>()
			);

			_events = new List<DomainEvent<TKey>>();
			Stamp = DateTime.MinValue;
			Sequence = -1;

			//BeforeApplyEvent<DomainEvent<TKey>>(e => e.Sequence = ++Sequence);
			BeforeApplyEvent<DomainEvent<TKey>>(e => e.Stamp = _getTimestamp());
		}

		public IEnumerable<DomainEvent<TKey>> GetUncommittedEvents()
		{
			return _events;
		}

		internal void MarkEventsCommitted()
		{
			if (_events.Any())
			{
				Stamp = _events.Last().Stamp;
				Sequence = _events.Last().Sequence;
				_events.Clear();
			}
		}

		internal void LoadFromEvents(IEnumerable<DomainEvent<TKey>> eventStream)
		{
			DomainEvent<TKey> last = null;
			var dynamic = this.AsDynamic();

			eventStream
				.Apply(e => last = e)
				.ForEach(e => dynamic.Handle(e));

			if (last != null)
			{
				Stamp = last.Stamp;
				Sequence = last.Sequence;
			}
		}

		internal void LoadFromSnapshot<TSnapshot>(TSnapshot snapshot, IEnumerable<DomainEvent<TKey>> events)
			where TSnapshot : Snapshot<TKey>
		{
			if (snapshot != null)
			{
				this.AsDynamic().ApplySnapshot(snapshot);
				Stamp = snapshot.Stamp;
				Sequence = snapshot.Sequence;
				ID = snapshot.AggregateID;
			}

			LoadFromEvents(events);
		}

		protected void BeforeApplyEvent<TEvent>(Action<TEvent> handler)
			where TEvent : DomainEvent<TKey>
		{
			_handlers[typeof(TEvent)].Add(e => handler((TEvent)e));
		}

		protected void ApplyEvent(DomainEvent<TKey> @event)
		{
			var eventType = @event.GetType();

			_handlers
				.Dictionary<commit_msg>aggregateRate: allow aggregates to be populated externally<commit_after>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Ledger.Infrastructure;

namespace Ledger
{
	public class AggregateRoot<TKey>
	{
		public TKey ID { get; protected set; }
		protected internal DateTime Stamp { get; set; }
		protected internal int Sequence { get; set; }

		private readonly Func<DateTime> _getTimestamp;
		private readonly LightweightCache<Type, List<Action<DomainEvent<TKey>>>> _handlers;
		private readonly List<DomainEvent<TKey>> _events;

		protected AggregateRoot()
			: this(DefaultStamper.Now)
		{
		}

		protected AggregateRoot(Func<DateTime> getTimestamp)
		{
			_getTimestamp = getTimestamp;
			_handlers = new LightweightCache<Type, List<Action<DomainEvent<TKey>>>>(
				key => new List<Action<DomainEvent<TKey>>>()
			);

			_events = new List<DomainEvent<TKey>>();
			Stamp = DateTime.MinValue;
			Sequence = -1;

			//BeforeApplyEvent<DomainEvent<TKey>>(e => e.Sequence = ++Sequence);
			BeforeApplyEvent<DomainEvent<TKey>>(e => e.Stamp = _getTimestamp());
		}

		public IEnumerable<DomainEvent<TKey>> GetUncommittedEvents()
		{
			return _events;
		}

		internal void MarkEventsCommitted()
		{
			if (_events.Any())
			{
				Stamp = _events.Last().Stamp;
				Sequence = _events.Last().Sequence;
				_events.Clear();
			}
		}

		public void LoadFromEvents(IEnumerable<DomainEvent<TKey>> eventStream)
		{
			DomainEvent<TKey> last = null;
			var dynamic = this.AsDynamic();

			eventStream
				.Apply(e => last = e)
				.ForEach(e => dynamic.Handle(e));

			if (last != null)
			{
				Stamp = last.Stamp;
				Sequence = last.Sequence;
			}
		}

		public void LoadFromSnapshot<TSnapshot>(TSnapshot snapshot, IEnumerable<DomainEvent<TKey>> events)
			where TSnapshot : Snapshot<TKey>
		{
			if (snapshot != null)
			{
				this.AsDynamic().ApplySnapshot(snapshot);
				Stamp = snapshot.Stamp;
				Sequence = snapshot.Sequence;
				ID = snapshot.AggregateID;
			}

			LoadFromEvents(events);
		}

		protected void BeforeApplyEvent<TEvent>(Action<TEvent> handler)
			where TEvent : DomainEvent<TKey>
		{
			_handlers[typeof(TEvent)].Add(e => handler((TEvent)e));
		}

		protected void ApplyEvent(DomainEvent<TKey> @event)
		{
			var eventType = @event.GetType();

			_handlers
				.Dictionary
{'fraction_non_alphanumeric': 0.1237848347375243, 'fraction_numerical': 0.00043205875999135883, 'mean_word_length': 4.0823271130625685, 'pattern_counts': {'":': 0, '<': 73, '<?xml version=': 0, '>': 85, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5488226', 'n_tokens_mistral': 1770, 'n_tokens_neox': 1489, 'n_words': 305}