using System;
using System.Collections;
using System.Data;
using System.Data.OleDb;

namespace Telerik.Web.Examples
{
	/// <summary>
	/// Retrieves data from the database and serves content to the DBContentProvider
	/// </summary>
	public class DataServer
	{
		private string _connectionString = null;
		private string ConnectionString
		{
			get
			{
				return _connectionString;
			}
		}


		private OleDbConnection _connection;
		private OleDbConnection Connection
		{
			get
			{
				if (_connection == null)
				{
					_connection = new OleDbConnection(ConnectionString);
				}
				return _connection;
			}
		}
		

		private DataTable _data;
		private DataTable Data
		{
			get
			{
				if (_data == null)
				{
					OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT ItemID, [Name], ParentID, MimeType, IsDirectory, [Size] FROM Items ORDER BY ItemID", Connection);
					Connection.Open();
					_data = new DataTable();
					adapter.Fill(_data);
					CloseConnection();
				}
				return _data;
			}
		}

		
		/// <summary>
		/// Creates an instance of the DataServer class
		/// </summary>
		/// <param name="connectionString"></param>
		public DataServer(string connectionString)
		{
			_connectionString = connectionString;
		}


		private void CloseConnection()
		{
			if(Connection.State != ConnectionState.Closed)
			{
				Connection.Close();
			}
		}
		
		private int GetItemId(string path)
		{
			DataRow itemRow = GetItemRow(path);
			if (itemRow == null)
			{
				return -1;
			}
			return (int)itemRow["ItemID"];
		}

		public DataRow[] GetChildDirectoryRows(string path)
		{
			return Data.Select(string.Format("ParentID={0} AND IsDirectory", GetItemId(path)));
		}

		public DataRow[] GetChildFileRows(string path)
		{
			return Data.Select(string.Format("ParentID={0} AND NOT IsDirectory", GetItemId(path)));
		}

		public DataRow GetItemRow(string path)
		{
			if (path.EndsWith("/"))
			{
				path = path.Substring(0, path.Length - 1);
			}
			string[] names = path.Split('/');
			//Start search in root;
			DataRow searchedRow = null;
			int itemId = 0;
			for (int i=0; i<names.Length; i++)
			{
				string name = names[i];
				DataRow[] rows = Data.Select(string.Format("Name='{0}' AND (ParentID={1} OR {1}=0)", name.Replace("'", "''"), itemId));
				if (rows.Length == 0)
				{
					return null;
				}
				searchedRow = rows[0];
				itemId = (int)searchedRow["ItemID"];
			}
			return searchedRow;
		}
		public byte[] GetContent(string path)
		{
			int itemId = GetItemId(path);
			if(itemId <= 0)
			{
				return null;
			}
			OleDbCommand command = new OleDbCommand("SELECT Content FROM Items WHERE ItemID = @ItemID", Connection);
			command.Parameters.Add(new OleDbParameter("@ItemID", itemId));
			Connection.Open();
			byte[] returnValue = (byte[])command.ExecuteScalar();
			CloseConnection();
			return returnValue;
		}

		public void CreateItem(string name, string path, string mimeType, bool isDirectory, long size, byte[] content)
		{
			int parentId = GetItemId(path);
			if (parentId < 0)
			{
				return;
			}
			OleDbCommand command =
				new OleDbCommand(
					"INSERT INTO Items ([Name], ParentId, MimeType, IsDirectory, [Size], Content) VALUES (@Name, @ParentId, @MimeType, @IsDirectory, @Size, @Content)", Connection);
			command.Parameters.Add(new OleDbParameter("@Name", name));
			command.Parameters.Add(new OleDbParameter("@ParentId", parentId));
			command.Parameters.Add(new OleDbParameter("@MimeType", mimeType));
			command.Parameters.Add(new OleDbParameter("@IsDirectory", isDirectory));
			command.Parameters.Add(new OleDbParameter("@Size", size));
			command.Parameters.Add(new OleDbParameter("@Content", content));
			Connection.Open();
			command.ExecuteNonQuery();
			CloseConnection();
			_data = null;
		}
		
		public void DeleteItem(string path)
		{
			int itemId = GetItemId(path);
			if (itemId <= 0)
			{
				return;
			}
			OleDbCommand command = new OleDbCommand("DELETE FROM Items WHERE ItemID=@ItemID", Connection);
			command.Parameters.Add(new OleDbParameter("@ItemID", itemId));
			Connection.Open();
			command.ExecuteNonQuery();
			CloseConnection();
			_data = null;
		}
		
		public DataRow[] GetAllDirectoryRows(string path)
		{
			DataRow rootRow = GetItemRow(path);
			if (rootRow == null)
			{
				return new DataRow[] {};
			}
			ArrayList allDirectoryRows = new ArrayList();
			allDirectoryRows.Add(rootRow);
			FillChildDirectoryRows((int)rootRow["ItemID"], allDirectoryRows);
			return (DataRow[])allDirectoryRows.ToArray(typeof(DataRow));
		}
		
		private void FillChildDirectoryRows(int parentId, ArrayList toFill)
		{
			DataRow[] childRows = Data.Select(string.Format("ParentID={0} AND IsDirectory", parentId));
			foreach(DataRow childRow in childRows)
			{
				toFill.Add(childRow);
				FillChildDirectoryRows((int)childRow["ItemID"], toFill);
			}
		}
		
		public string GetItemPath(DataRow row)
		{
			if (row["ParentID"] is DBNull)
			{
				return string.Format("{0}/", row["Name"]);
			}
			int parentId = (int)row["ParentID"];
			DataRow[] parents = Data.Select(string.Format("ItemID={0}", parentId));
			if (parents.Length == 0)
			{
				return string.Format("/{0}", row["Name"]);
			}
			return GetItemPath(parents[0]) + string.Format("{0}/", row["Name"]);
		}

		public void ReplaceItemContent(string path, byte[] content)
		{
			int itemId = GetItemId(path);
			if (itemId < 0)
			{
				return;
			}
			OleDbCommand command = new OleDbCommand("UPDATE Items SET Content=@Content WHERE ItemID=@ItemID", Connection);
			command.Parameters.Add(new OleDbParameter("@Content", content));
			command.Parameters.Add(new OleDbParameter("@ItemID", itemId));
			Connection.Open();
			command.ExecuteNonQuery();
			CloseConnection();
		}
	}
}