using System;
using System.IO;
using System.Collections;
using Orciid.Media.Converters;

namespace Orciid.Media
{
	public delegate bool FileConverter(string infile, string outfile, Parameters parameters);

	public class MediaConverter
	{
		private MediaConverter()
		{
		}

		static MediaConverter()
		{
			RegisterConverters();
		}

		public static void RegisterConverters()
		{
			if (converters.Count == 0)
			{
				Converters.BitmapConverter.Register();
				Converters.Jpeg2000Converter.Register();
			}
		}
		
		private static ArrayList converters = new ArrayList();

		public static bool Convert(string source, string target)
		{
			return Convert(source, target, Parameters.Default);
		}

		public static bool Convert(string sourcefile, string targetfile, Parameters parameters)
		{
			if (!File.Exists(sourcefile))
				throw new IOException("Source file not found");
			string fromtype = MimeType.GetFromExtension(sourcefile);
			string totype = MimeType.GetFromExtension(targetfile);
			FileConverter converter = GetFileConverter(fromtype, totype, parameters);
			if (converter == null)
				throw new ArgumentException(String.Format(
				"Required file converter not registered: {0} to {1}", fromtype, totype));
			return converter(sourcefile, targetfile, parameters);
		}

		internal struct ConverterRegistration
		{
			public string FromType;
			public string ToType;
			public Capabilities Capabilities;
			public bool Internal;
			public FileConverter Converter;
		}

		public static void RegisterFileConverter(string fromtype, string totype, 
			Capabilities capabilities, bool intern, FileConverter converter)
		{
			lock (converters)
			{
				ConverterRegistration reg;
				reg.FromType = fromtype;
				reg.ToType = totype;
				reg.Capabilities = capabilities;
				reg.Internal = intern;
				reg.Converter = converter;
				converters.Add(reg);
			}
		}

		public static void UnRegisterFileConverter(FileConverter converter)
		{
			lock (converters)
			{
				for (int i = converters.Count - 1; i >= 0; i--)
					if (((ConverterRegistration)converters[i]).Converter == converter)
						converters.RemoveAt(i);
			}
		}

		internal static IEnumerable GetRegisteredConverters()
		{
			return converters.Clone() as ArrayList;
		}
		
		public static FileConverter GetFileConverter(string fromtype, string totype)
		{
			return GetFileConverter(fromtype, totype, Parameters.Default);
		}

		public static FileConverter GetFileConverter(string fromtype, string totype,
			Parameters parameters)
		{
			foreach (ConverterRegistration reg in converters)
				if (fromtype == reg.FromType && totype == reg.ToType &&
					parameters.WithinCapabilities(reg.Capabilities))
					return reg.Converter;
			return null;
		}
	}
}
