//------------------------------------------------------------------------------
// <copyright company="Telligent Systems">
//     Copyright (c) Telligent Systems Corporation.  All rights reserved.
// </copyright> 
//------------------------------------------------------------------------------

using System;
using System.Collections;
using System.IO;
using System.Reflection;
using System.Web;
using CommunityServer.Components;

namespace CommunityServer.Spam
{
	/// <summary>
	/// Searches assemblies for Spam Rules (subclasses of SpamRule)
	/// </summary>
	[Serializable]
	internal class RuleLoader
	{
		#region Members...
		private string _searchDirectory = "~/bin";
		#endregion

		#region Contructors...
		/// <summary>
		/// Default constructor
		/// </summary>
		public RuleLoader()
		{
		}
		#endregion

		#region Properties
		/// <summary>
		/// Read/write access to the directory to search for rules
		/// </summary>
		public string SearchDirectory
		{
			get { return _searchDirectory; }
			set { _searchDirectory = value; }
		}
		#endregion

		#region Methods...
		/// <summary>
		/// Responsible for loading spam rules
		/// </summary>
		/// <returns></returns>
		public ArrayList LoadRules()
		{
			ArrayList rules = new ArrayList();

			// Figure out where to look for rules
			string path = string.Empty;
			HttpContext context = HttpContext.Current;
			if (context != null)
				path = CSContext.Current.MapPath(this.SearchDirectory);
			else
				path = AppDomain.CurrentDomain.BaseDirectory + this.SearchDirectory;

			// Load all rules found
			string[] assemblies = Directory.GetFileSystemEntries(path, "*.dll");
			for (int i = 0; i < assemblies.Length; i++)
			{
				try
				{
					Assembly asm = Assembly.LoadFrom(assemblies[i]);
					SearchForRules(asm, rules);
				}
				catch
				{
					// Should we eat this exception or log it somewhere??
				}
			}

			return rules;
		}


		/// <summary>
		/// Responsible for finding spam rules in an assembly
		/// </summary>
		/// <param name="asm"></param>
		/// <param name="rules"></param>
		private void SearchForRules(Assembly asm, ArrayList rules)
		{
			ArrayList foundTypes = new ArrayList();
			foreach (Type t in asm.GetTypes())
			{
				if ((t.IsPublic) && (t.IsSubclassOf(typeof(SpamRule))))
					foundTypes.Add(t);
			}

			foreach (Type t in foundTypes)
			{
				try
				{
					SpamRule rule = asm.CreateInstance(t.FullName) as SpamRule;
					rules.Add(rule);
				}
				catch
				{
					// Should we eat this exception or log it somewhere??
				}
			}
		}
		#endregion
	}
}
