<commit_before>using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using RestSharp;

namespace LazyPI.LazyObjects
{
	public class AFElement : LazyPI.BaseObject
	{
		private Lazy<AFElementTemplate> _Template;
		private Lazy<AFElement> _Parent;
		private Lazy<ObservableCollection<AFElement>> _Children;
		private Lazy<ObservableCollection<AFAttribute>> _Attributes;
		private static IAFElement _ElementLoader;

		#region "Properties"
			public AFElementTemplate Template
			{
				get
				{
					return _Template.Value;
				}
			}

			public AFElement Parent
			{
				get
				{
					return _Parent.Value;
				}
			}

			public ObservableCollection<AFElement> Children
			{
				get
				{
					return _Children.Value; 
				}
			}

			public ObservableCollection<AFAttribute> Attributes
			{
				get
				{
					return _Attributes.Value;
				}
			}
		#endregion

		#region "Constructors"
			private AFElement(string ID, string Name, string Description, string Path) : base(ID, Name, Description, Path)
			{
				Initialize();
			}

			public AFElement(string ID)
			{
				BaseObject baseObj = _ElementLoader.Find(ID);

				this._ID = baseObj.ID;
				this._Name = baseObj.Name;
				this._Description = baseObj.Description;
				this._Path = baseObj.Path;

				Initialize();
			}

			/// <summary>
			/// Builds loader object and sets all callbacks for lazy loading 
			/// </summary>
			private void Initialize()
			{
				//Load Template
				_Template = new Lazy<AFElementTemplate>(() =>
				{
					string templateName = _ElementLoader.GetElementTemplate(this._ID);
					return new AFElementTemplate(templateName);
				}, System.Threading.LazyThreadSafetyMode.ExecutionAndPublication);


				//Load Parent
				string parentPath = Path.Substring(0, Path.LastIndexOf('\\')); 
				
				_Parent = new Lazy<AFElement>(() =>
				{
					return ElementFactory.CreateInstance(_ElementLoader.FindByPath(parentPath));
				}, System.Threading.LazyThreadSafetyMode.ExecutionAndPublication);

				//Load Attributes
				_Attributes = new Lazy<ObservableCollection<AFAttribute>>(() => 
				{
					List<AFAttribute> resultList = ElementFactory.CreateList(_ElementLoader.GetAttributes(this.ID));
					ObservableCollection<AFAttribute> obsList = new ObservableCollection<AFAttribute>(resultList);
					obsList.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(AttributesChanged);
					return obsList;
				}, System.Threading.LazyThreadSafetyMode.ExecutionAndPublication);

				//Load Children
				_Children = new Lazy<ObservableCollection<AFElement>>(() =>
				{
					List<AFElement> resultList = ElementFactory.CreateList(_ElementLoader.GetElements(this.ID));
					ObservableCollection<AFElement> obsList = new ObservableCollection<AFElement>(resultList);
					obsList.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(ChildrenChanged);
					return obsList;
				}, System.Threading.LazyThreadSafetyMode.ExecutionAndPublication);
			}

			private void AttributesChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
			{
				//TODO: Implement
			}

			/// <summary>
			/// Notifies when developer makes changes to list. This method makes call back to insure PI is up to date.
			/// </summary>
			/// <param name="sender">Object that triggered the change.</param>
			/// <param name="e">Arguments that define the event.</param>
			private void ChildrenChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
			{
				if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
				{
					_ElementLoader.CreateChildElement(this._ID, (AFElement)sender);
				}
				else if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
				{
					AFElement element = (AFElement)sender;
					Delete(element._ID);
				}
				else if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace)
				{
					throw new NotImplementedException("Replace is not supported by LazyPI.");
				}
			}

		#endregion

		#region "Interactions"
			public void CheckIn()
			{
				_ElementLoader.Update(this);
			}
		#endregion

		#region "Static Methods"
		/// <summary>
		/// Returns element requested
		/// </summary>
		/// <param name="ID"></param>
		/// <returns></returns>
		public static AFElement Find(string ID)
		{
			return ElementFactory.CreateInstance(_ElementLoader.Find(ID));
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="Path"></param>
		/// <returns></returns>
		public static AFElement FindByPath(string Path)
		{
			return ElementFactory.CreateInstance(_ElementLoader.FindByPath(Path));
		}

		/// <summary>
		/// Removes specific element from AF Database
		/// </summary>
		/// <param name="ElementID">The ID of the element to be deleted</param>
		/// <returns></returns>
		public static bool Delete(string ElementID)
		{
			return _ElementLoader.Delete(ElementID);
		}

		//TODO: Implement Find Element By Category
		public static IEnumerable<AFElement> FindByCategory(string CategoryName)
		{
			throw new NotImplementedException();
		}

		//TODO: Implement Find Element By Template
		public static IEnumerable<AFElement> FindByTemplate(string TemplateName)
		{
			throw new NotImplementedException();
		}
		#endregion

		/// <summary>
		/// Uses the hidden constructor to create full instances of AFElement.
		/// </summary>
		public class ElementFactory
		{
			public static AFElement CreateInstance(BaseObject bObj)
			{
				return new AFElement(bObj.ID, bObj.Name, bObj.Description, bObj.Path);
			}

			public static AFElement CreateInstance(string ID, string Name, string Description, string Path)
			{
				return new AFElement(ID, Name, Description, Path);
			}

			public static List<AFElement> CreateList(IEnumerable<BaseObject> Elements)
			{
				List<AFElement> elementList = new List<AFElement>();

				foreach(AFElement element in Elements)
				{
					elementList.Add(new AFElement(element.ID, element.Name, element.Description, element.Path));
				}

				return elementList;<commit_msg>Completed search for elements by template and search for by category.<commit_after>using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using RestSharp;

namespace LazyPI.LazyObjects
{
	public class AFElement : LazyPI.BaseObject
	{
		private Lazy<AFElementTemplate> _Template;
		private Lazy<AFElement> _Parent;
		private Lazy<ObservableCollection<AFElement>> _Children;
		private Lazy<ObservableCollection<AFAttribute>> _Attributes;
		private static IAFElement _ElementLoader;

		#region "Properties"
			public AFElementTemplate Template
			{
				get
				{
					return _Template.Value;
				}
			}

			public AFElement Parent
			{
				get
				{
					return _Parent.Value;
				}
			}

			public ObservableCollection<AFElement> Children
			{
				get
				{
					return _Children.Value; 
				}
			}

			public ObservableCollection<AFAttribute> Attributes
			{
				get
				{
					return _Attributes.Value;
				}
			}
		#endregion

		#region "Constructors"
			private AFElement(string ID, string Name, string Description, string Path) : base(ID, Name, Description, Path)
			{
				Initialize();
			}

			public AFElement(string ID)
			{
				BaseObject baseObj = _ElementLoader.Find(ID);

				this._ID = baseObj.ID;
				this._Name = baseObj.Name;
				this._Description = baseObj.Description;
				this._Path = baseObj.Path;

				Initialize();
			}

			/// <summary>
			/// Builds loader object and sets all callbacks for lazy loading 
			/// </summary>
			private void Initialize()
			{
				//Load Template
				_Template = new Lazy<AFElementTemplate>(() =>
				{
					string templateName = _ElementLoader.GetElementTemplate(this._ID);
					return new AFElementTemplate(templateName);
				}, System.Threading.LazyThreadSafetyMode.ExecutionAndPublication);


				//Load Parent
				string parentPath = Path.Substring(0, Path.LastIndexOf('\\')); 
				
				_Parent = new Lazy<AFElement>(() =>
				{
					return ElementFactory.CreateInstance(_ElementLoader.FindByPath(parentPath));
				}, System.Threading.LazyThreadSafetyMode.ExecutionAndPublication);

				//Load Attributes
				_Attributes = new Lazy<ObservableCollection<AFAttribute>>(() => 
				{
					List<AFAttribute> resultList = ElementFactory.CreateList(_ElementLoader.GetAttributes(this.ID));
					ObservableCollection<AFAttribute> obsList = new ObservableCollection<AFAttribute>(resultList);
					obsList.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(AttributesChanged);
					return obsList;
				}, System.Threading.LazyThreadSafetyMode.ExecutionAndPublication);

				//Load Children
				_Children = new Lazy<ObservableCollection<AFElement>>(() =>
				{
					List<AFElement> resultList = ElementFactory.CreateList(_ElementLoader.GetElements(this.ID));
					ObservableCollection<AFElement> obsList = new ObservableCollection<AFElement>(resultList);
					obsList.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(ChildrenChanged);
					return obsList;
				}, System.Threading.LazyThreadSafetyMode.ExecutionAndPublication);
			}

			private void AttributesChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
			{
				//TODO: Implement
			}

			/// <summary>
			/// Notifies when developer makes changes to list. This method makes call back to insure PI is up to date.
			/// </summary>
			/// <param name="sender">Object that triggered the change.</param>
			/// <param name="e">Arguments that define the event.</param>
			private void ChildrenChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
			{
				if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
				{
					_ElementLoader.CreateChildElement(this._ID, (AFElement)sender);
				}
				else if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
				{
					AFElement element = (AFElement)sender;
					Delete(element._ID);
				}
				else if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace)
				{
					throw new NotImplementedException("Replace is not supported by LazyPI.");
				}
			}

		#endregion

		#region "Interactions"
			public void CheckIn()
			{
				_ElementLoader.Update(this);
			}
		#endregion

		#region "Static Methods"
		/// <summary>
		/// Returns element requested
		/// </summary>
		/// <param name="ID"></param>
		/// <returns></returns>
		public static AFElement Find(string ID)
		{
			return ElementFactory.CreateInstance(_ElementLoader.Find(ID));
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="Path"></param>
		/// <returns></returns>
		public static AFElement FindByPath(string Path)
		{
			return ElementFactory.CreateInstance(_ElementLoader.FindByPath(Path));
		}

		/// <summary>
		/// Removes specific element from AF Database
		/// </summary>
		/// <param name="ElementID">The ID of the element to be deleted</param>
		/// <returns></returns>
		public static bool Delete(string ElementID)
		{
			return _ElementLoader.Delete(ElementID);
		}

		/// <summary>
		/// Find all of the child elements with a specific category.
		/// </summary>
		/// <param name="CategoryName">Name of the category to be searched for.</param>
		/// <param name="MaxCount">Max number of elements that should be searched for.</param>
		/// <returns>A list of elements that have a specific category.</returns>
		public IEnumerable<AFElement> FindByCategory(string CategoryName, int MaxCount = 1000)
		{
			var baseList = _ElementLoader.GetElements(this._ID, "*", CategoryName, "*", ElementType.Any, false, "Name", "Ascending", 0, MaxCount);

			return ElementFactory.CreateList(baseList);
		}

		/// <summary>
		/// Find all of the child elements with a specific template.
		/// </summary>
		/// <param name="TemplateName">Name of the template to be searched for.</param>
		/// <param name="MaxCount">Max number of elements that should be searched for.</param>
		/// <returns>A list of elements that have a specific template.</returns>
		public IEnumerable<AFElement> FindByTemplate(string TemplateName, int MaxCount = 1000)
		{
			var baseList = _ElementLoader.GetElements(this._ID, "*", "*", TemplateName, ElementType.Any, false, "Name", "Ascending", 0, MaxCount);

			return ElementFactory.CreateList(baseList);
		}
		#endregion

		/// <summary>
		/// Uses the hidden constructor to create full instances of AFElement.
		/// </summary>
		public class ElementFactory
		{
			public static AFElement CreateInstance(BaseObject bObj)
			{
				return new AFElement(bObj.ID, bObj.Name, bObj.Description, bObj.Path);
			}

			public static AFElement CreateInstance(string ID, string Name, string Description, string Path)
			{
				return new AFElement(ID, Name, Description, Path);
			}

			public static List<AFElement> CreateList(IEnumerable<BaseObject> Elements)
			{
				List<AFElement> elementList = new List<AFElement>();

				foreach(AFElement element in Elements)
				{
					elementList.Add(new AFElement(element.ID, element.Name, element.Description, element.Path));
				}

				return elementList;
{'fraction_non_alphanumeric': 0.10974152099208127, 'fraction_numerical': 0.0008964589870013447, 'mean_word_length': 3.677498252969951, 'pattern_counts': {'":': 0, '<': 127, '<?xml version=': 0, '>': 135, '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': '5092651', 'n_tokens_mistral': 4585, 'n_tokens_neox': 3739, 'n_words': 891}