using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;

namespace %%%PROJECT_ID%%%
{
	internal static class ResourceReader
	{
		public static string ReadTextResource(string path)
		{
			return ReadTextFile(path, true);
		}

		public static string ReadTextFile(string path, bool filePrefix)
		{
			IList<byte> bytes = ReadBytes(path, filePrefix);
			if (bytes == null)
			{
				return null;
			}
			StringBuilder output = new StringBuilder(bytes.Count); 
			output.Append(ReadBytes(path, filePrefix).Select<byte, char>(b => (char)b).ToArray<char>());
			return output.ToString();
		}

		public static string ReadByteCodeFile()
		{
			return ReadTextFile("ByteCode.txt", false);
		}

		public static System.Drawing.Bitmap ReadImageFile(string path, bool generatedImage)
		{
			IList<byte> data = ReadBytes(path, !generatedImage);
			if (data == null)
			{
				return null;
			}
			return new Bitmap(Bitmap.FromStream(new MemoryStream(data.ToArray<byte>())));
		}

		public static System.IO.Stream GetResourceStream(string path, bool useFilePrefix)
		{
			// TODO: C# likes to replace non alphanumerics in the path with underscores but 
			// only in the directories, not in the actual file name. Will need to come up
			// with some original resource mapping to generated file names.
			path = path.Replace('\\', '/');
			string[] parts = path.Split('/');
			string original_file = parts[parts.Length - 1];
			List<string> final_file = new List<string>();
			for (int i = 0; i < parts.Length - 1; ++i)
			{
				final_file.Add(parts[i].Replace('-', '_'));
			}
			final_file.Add(original_file);
			string canonicalizedPath = string.Join(".", final_file);
			string prefix = "%%%PROJECT_ID%%%" + (useFilePrefix ? ".Files" : "") + (canonicalizedPath.StartsWith(".") ? "" : ".");
			canonicalizedPath = prefix + canonicalizedPath;

			return typeof(ResourceReader).Assembly.GetManifestResourceStream(canonicalizedPath);
		}

		private const int BUFFER_LENGTH = 128;
		private static readonly byte[] BUFFER = new byte[BUFFER_LENGTH];

		public static IList<byte> ReadBytes(string path, bool filePrefix)
		{
			System.IO.Stream stream = GetResourceStream(path, filePrefix);
			if (stream == null)
			{
				return null;
			}
			StringBuilder sb = new StringBuilder();
			List<byte> output = new List<byte>();

			int bytesRead = 1;
			while (bytesRead > 0)
			{
				bytesRead = stream.Read(BUFFER, 0, BUFFER_LENGTH);
				if (bytesRead == BUFFER_LENGTH)
				{
					output.AddRange(BUFFER);
				}
				else
				{
					for (int i = 0; i < bytesRead; ++i)
					{
						output.Add(BUFFER[i]);
					}
					bytesRead = 0;
				}
			}
			return output;
		}
	}
}
