using System;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using Telerik.Web.UI.Widgets;
using System.Collections.Generic;
using System.Collections;

namespace Telerik.Web.Examples
{
	//FileBrowserContentProvider
	public class DBContentProvider : FileBrowserContentProvider
	{
		private DataServer _dataServer;
		private DataServer DataServer
		{
			get
			{
				if (Object.Equals(_dataServer, null))
				{
					string connectionString =
						string.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};User ID=;Password=;",
									  Context.Server.MapPath(ConfigurationManager.AppSettings["Telerik.WebControls.EditorExamples.FileBrowserDatabase"]));
					_dataServer = new DataServer(connectionString);
				}
				return _dataServer;
			}
		}

		private string _itemHandlerPath;
		private string ItemHandlerPath
		{
			get
			{
				return _itemHandlerPath;
			}
		}

		private PathPermissions fullPermissions = PathPermissions.Read | PathPermissions.Delete | PathPermissions.Upload;

		public DBContentProvider(HttpContext context, string[] searchPatterns, string[] viewPaths, string[] uploadPaths, string[] deletePaths, string selectedUrl, string selectedItemTag)
			:
			base(context, searchPatterns, viewPaths, uploadPaths, deletePaths, selectedUrl, selectedItemTag)
		{
			_itemHandlerPath = ConfigurationManager.AppSettings["Telerik.WebControls.EditorExamples.ItemHandler"];
			if (_itemHandlerPath.StartsWith("~/"))
			{
				_itemHandlerPath = HttpContext.Current.Request.ApplicationPath + _itemHandlerPath.Substring(1);
			}
			if (SelectedItemTag != null && SelectedItemTag != string.Empty)
			{
				SelectedItemTag = ExtractPath(RemoveProtocolNameAndServerName(SelectedItemTag));
			}
		}


		private string GetItemUrl(string virtualItemPath)
		{
			return string.Format("{0}?path={1}", ItemHandlerPath, virtualItemPath);
		}

		private string ExtractPath(string itemUrl)
		{
			if (itemUrl == null)
			{
				return string.Empty;
			}
			if (itemUrl.StartsWith(_itemHandlerPath))
			{
				return itemUrl.Substring(GetItemUrl(string.Empty).Length);
			}
			return itemUrl;
		}

		private string GetName(string path)
		{
			if (path == null)
			{
				return string.Empty;
			}
			return path.Substring(path.LastIndexOf('/') + 1);
		}


		private string GetDirectoryPath(string path)
		{
			return path.Substring(0, path.LastIndexOf('/') + 1);
		}

		private bool IsChildOf(string parentPath, string childPath)
		{
			return childPath.StartsWith(parentPath);
		}

		private string EndWithSlash(string path)
		{
			if (!path.EndsWith("/"))
			{
				return path + "/";
			}
			return path;
		}

		private string CombinePath(string path1, string path2)
		{
			if (path1.EndsWith("/"))
			{
				return string.Format("{0}{1}", path1, path2);
			}
			if (path1.EndsWith("\\"))
			{
				path1 = path1.Substring(0, path1.Length - 1);
			}
			return string.Format("{0}/{1}", path1, path2);
		}

		private DirectoryItem[] GetChildDirectories(string path)
		{
			List<DirectoryItem> directories = new List<DirectoryItem>();
			if (IsChildOf(path, ExtractPath(SelectedUrl)))
			{
				DataRow[] childRows = DataServer.GetChildDirectoryRows(path);
				int i = 0;
				while (i < childRows.Length)
				{
					DataRow childRow = childRows[i];
					string name = childRow["Name"].ToString();
					string itemFullPath = EndWithSlash(CombinePath(path, name));
					directories.Add(new DirectoryItem(name, string.Empty, itemFullPath, itemFullPath, fullPermissions, GetChildFiles(itemFullPath), GetChildDirectories(itemFullPath)));
					i = i + 1;
				}
				return directories.ToArray();
			}
			return new DirectoryItem[] { };
		}

		private FileItem[] GetChildFiles(string _path)
		{
			if (IsChildOf(_path, ExtractPath(SelectedUrl)))
			{
				DataRow[] childRows = DataServer.GetChildFileRows(_path);
				ArrayList files = new ArrayList();

				for (int i = 0; i < childRows.Length; i++)
				{
					DataRow childRow = childRows[i];
					string name = childRow["Name"].ToString();
					if (IsExtensionAllowed(System.IO.Path.GetExtension(name)))
					{
						string itemFullPath = CombinePath(_path, name);
						files.Add(
							new FileItem(name, Path.GetExtension(name), (int)childRow["Size"], string.Empty, GetItemUrl(itemFullPath),
										 itemFullPath, fullPermissions));
					}
				}
				return (FileItem[])files.ToArray(typeof(FileItem));
			}
			return new FileItem[] { };
		}

		private bool IsExtensionAllowed(string extension)
		{
			return Array.IndexOf(SearchPatterns, "*.*") >= 0 || Array.IndexOf(SearchPatterns, "*" + extension.ToLower()) >= 0;
		}
		private string RemoveLastSlash(string path)
		{
			if (path.EndsWith("/"))
			{
				return path.Substring(0, path.Length - 1);
			}
			return path;
		}

		/// <summary>
		/// Loads a root directory with given path, where all subdirectories 
		/// contained in the SelectedUrl property are loaded
		/// </summary>
		/// <remarks>
		/// The ImagesPaths, DocumentsPaths, etc properties of RadEditor
		/// allow multiple root items to be specified, separated by comma, e.g.
		/// Photos,Paintings,Diagrams. The FileBrowser class calls the 
		/// ResolveRootDirectoryAsTree method for each of them.
		/// </remarks>
		/// <param name="path">the root directory path, passed by the FileBrowser</param>
		/// <returns>The root DirectoryItem or null if such does not exist</returns>
		public override DirectoryItem ResolveRootDirectoryAsTree(string path)
		{
			DirectoryItem returnValue =
				new DirectoryItem(GetName(path), GetDirectoryPath(path), path, string.Empty, fullPermissions, GetChildFiles(path),
				GetChildDirectories(path));
			return returnValue;
		}

		public override DirectoryItem[] ResolveRootDirectoryAsList(string path)
		{
			DataRow[] directoryRows = DataServer.GetAllDirectoryRows(path);
			List<DirectoryItem> directories = new List<DirectoryItem>();
			for (int i = 0; i < directoryRows.Length; i++)
			{
				DataRow row = directoryRows[i];
				string fullPath = RemoveLastSlash(DataServer.GetItemPath(row));
				directories.Add(new DirectoryItem(row["Name"].ToString(), GetDirectoryPath(fullPath), string.Empty, string.Empty, fullPermissions, GetChildFiles(fullPath), new DirectoryItem[] { }));
			}
			return directories.ToArray();
		}

		public override DirectoryItem ResolveDirectory(string path)
		{
			DirectoryItem[] directories;
			if (DisplayMode == FileBrowserDisplayMode.List)
			{
				directories = new DirectoryItem[] { };
			}
			else
			{
				directories = GetChildDirectories(path);
			}
			return new DirectoryItem(GetName(path), EndWithSlash(GetDirectoryPath(path)), string.Empty, string.Empty, fullPermissions, GetChildFiles(path),
				directories);
		}

		public override string GetFileName(string url)
		{
			return GetName(url);
		}

		public override string GetPath(string url)
		{
			return GetDirectoryPath(ExtractPath(RemoveProtocolNameAndServerName(url)));
		}

		public override Stream GetFile(string url)
		{
			byte[] content = DataServer.GetContent(ExtractPath(RemoveProtocolNameAndServerName(url)));
			if (!Object.Equals(content, null))
			{
				return new MemoryStream(content);
			}
			return null;
		}

		public override string StoreBitmap(Bitmap bitmap, string url, ImageFormat format)
		{
			string newItemPath = ExtractPath(RemoveProtocolNameAndServerName(url));
			string name = GetName(newItemPath);
			string _path = GetPath(newItemPath);
			string tempFilePath = System.IO.Path.GetTempFileName();
			bitmap.Save(tempFilePath);
			byte[] content;
			using (FileStream inputStream = File.OpenRead(tempFilePath))
			{
				long size = inputStream.Length;
				content = new byte[size];
				inputStream.Read(content, 0, Convert.ToInt32(size));
			}

			if (File.Exists(tempFilePath))
			{
				File.Delete(tempFilePath);
			}

			DataServer.CreateItem(name, _path, "image/gif", false, content.Length, content);
			return string.Empty;
		}

		//New method
		public override string StoreFile(Telerik.Web.UI.UploadedFile file, string path, string name, params string[] arguments)
		{
			int fileLength = Convert.ToInt32(file.InputStream.Length);
			byte[] content = new byte[fileLength];
			file.InputStream.Read(content, 0, fileLength);
			string fullPath = CombinePath(path, name);
			if (!Object.Equals(DataServer.GetItemRow(fullPath), null))
			{
				DataServer.ReplaceItemContent(fullPath, content);
			}
			else
			{
				DataServer.CreateItem(name, path, file.ContentType, false, fileLength, content);
			}
			return string.Empty;
		}

		public override string DeleteFile(string path)
		{
			DataServer.DeleteItem(path);
			return string.Empty;
		}

		public override string DeleteDirectory(string path)
		{
			DataServer.DeleteItem(path);
			return string.Empty;
		}

		public override string CreateDirectory(string path, string name)
		{
			DataServer.CreateItem(name, path, string.Empty, true, 0, new byte[0]);
			return string.Empty;
		}

		public override bool CanCreateDirectory
		{
			get
			{
				return true;
			}
		}
	}
}