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

using System;
using System.Collections;
using System.Data;
using CommunityServer.Components;
using CommunityServer.Configuration;


namespace CommunityServer.Reader.Components
{
	/// <summary>
	/// Summary description for FeedReaderDataProvider.
	/// </summary>
	public abstract class FeedReaderDataProvider
	{


		#region Private Members

		public static readonly string FeedReaderDataProviderName = "FeedReaderDataProvider";

		#endregion

		#region Instance

		private static FeedReaderDataProvider _instance = null;

		static FeedReaderDataProvider()
		{
			CreateDefaultCommonProvider();
		}

		public static FeedReaderDataProvider Instance()
		{
			return _instance;
		}

		public static FeedReaderDataProvider Instance (Provider dataProvider) 
		{
			FeedReaderDataProvider frdp = CSCache.Get(dataProvider.Name) as FeedReaderDataProvider;
			if(frdp == null)
			{
				frdp = DataProviders.Invoke(dataProvider) as FeedReaderDataProvider;
				CSCache.Max(dataProvider.Name, frdp);
			}
			return frdp;
		}

		private static void CreateDefaultCommonProvider()
		{
			// Get the names of the providers
			//
			CSConfiguration config = CSConfiguration.GetConfig();

			// Read the configuration specific information
			// for this provider
			//
			Provider sqlForumsProvider = (Provider) config.Providers[FeedReaderDataProviderName];

			// Read the connection string for this provider
			//
            
			_instance = DataProviders.CreateInstance(sqlForumsProvider) as FeedReaderDataProvider;
		}

		#endregion


		public virtual ArrayList GetAllFeeds()
		{
		    return GetAllFeeds(0);
		}

        public abstract ArrayList GetAllFeeds(int minutes);
		public abstract void UpdateFeed(int feedId, string url, string title, string link, string language, string generator, DateTime subscribeDate, DateTime lastUpdateDate, DateTime lastModified, string eTag, int feedStateId);
		public abstract void UpdateFeedStatus(int feedId, FeedState state);
		public abstract void UpdateFeedPosts(int feedId, string feedItemList);
		public abstract ArrayList GetFolders(int userId, int parentFolderId);
		public abstract ArrayList GetFeeds(int userId, int folderId);
		public abstract ArrayList GetFeedPosts(int feedId, int userId);
		public abstract FeedPost GetPost(int feedPostId);
		public abstract void MarkPostRead(int userId, int feedId);
		public abstract void RenameFolder(int folderId, string newFolderName);
		public abstract int AddFolder(int userId, string folderName, int parentFolderId);
		public abstract int AddFeed(int userId, int folderId, string url);
		public abstract void DeleteFolder(int folderId);
		public abstract void DeleteFeed(int userId, int feedId);
		public abstract void MoveFeed(int folderFeedId, int newFolderId);
		public abstract void MoveFolder(int folderId, int newParentFolderId);
		public abstract ArrayList GetOpmlFeedsFolders(int userId);
		public abstract Feed GetFeedProperties(int feedId);
		public abstract FeedPost GetPostFullDetails(int feedId);
		public abstract ArrayList GetFolderSummary(int userId, int folderId);
		public abstract Feed GetFeed(int feedId);
		public abstract ArrayList GetUsers();

		// Roller methods
		public abstract FeedPostSet GetRollerPosts(int userID, int pageIndex, int pageSize);
		public abstract ArrayList GetRollerFeeds(int userId);
		public abstract ArrayList GetUnaggregatedFeeds(int userId);
		public abstract void AddAggregatedFeed(int userId, int feedId);

		#region Populate Helpers

		public static Feed PopulateFeedPropertiesFromIDataReader(IDataReader dr)
		{
			Feed feed = new Feed();


			feed.Generator		= dr["Generator"] as string;
			
			feed.Language		= dr["Language"] as string;		
			
			feed.LastUpdateDate	= (DateTime) dr["LastUpdateDate"];				
			
			feed.Link			=  dr["Link"] as string;				
			
			if (dr["SubscribeDate"] != DBNull.Value)
				feed.SubscribeDate	= (DateTime) dr["SubscribeDate"];				
									
			feed.Title			=  dr["Title"] as string;
			
			feed.Url			= (string) dr["Url"] as string;				
			
			if (dr["SubscribeCount"] != null)
				feed.SubscribeCount = (int) dr["SubscribeCount"];
			
			if (dr["PostCount"] != null)
				feed.PostCount = (int) dr["PostCount"];
			
			if (dr["StateName"] != null)
				feed.StateName = (string) dr["StateName"];
			
			if (dr["Description"] != null)
				feed.StateDescription = (string) dr["Description"];


			return feed;
		}

		public static Feed PopulateFeedFromIDataReader(IDataReader dr)
		{
			Feed feed = new Feed();


			if (dr["FeedId"] != DBNull.Value)
				feed.FeedId			= (int) dr["FeedId"];
		
			feed.Generator		= dr["Generator"] as string;

			feed.FeedState		= ResolveFeedState((int) dr["FeedStateId"]);
			
			feed.FeedStateId	= (int) dr["FeedStateId"];
			
			feed.Language		= dr["Language"] as string;		
			
			feed.LastUpdateDate	= (DateTime) dr["LastUpdateDate"];				
			
			feed.Link			=  dr["Link"] as string;				
			
			if (dr["SubscribeDate"] != DBNull.Value)
				feed.SubscribeDate	= (DateTime) dr["SubscribeDate"];				
			
			feed.ETag			= dr["Etag"] as string;				
			
			feed.LastModified	= (DateTime)dr["LastModified"];
			
			feed.Title			=  dr["Title"] as string;
			
			feed.Url			= (string) dr["Url"] as string;				
			
			return feed;
		}

		public static Feed PopulateBriefFeedFromIDataReader(IDataReader dr)
		{
			Feed feed = new Feed();


			if (dr["FeedId"] != DBNull.Value)
				feed.FeedId			= (int) dr["FeedId"];
			
			feed.Link			=  dr["Link"] as string;				
			
			feed.Title			=  dr["Title"] as string;
			
			feed.Url			= (string) dr["Url"] as string;				


			return feed;
		}

		public static Feed PopulateFullFeedFromIDataReader(IDataReader dr)
		{
			Feed feed = new Feed();


			if (dr["FeedId"] != DBNull.Value)
				feed.FeedId			= (int) dr["FeedId"];
		
			feed.Generator		= dr["Generator"] as string;

			feed.FeedState		= ResolveFeedState((int) dr["FeedStateId"]);
			
			feed.FeedStateId	= (int) dr["FeedStateId"];
			
			feed.Language		= dr["Language"] as string;		
			
			feed.LastUpdateDate	= (DateTime) dr["LastUpdateDate"];				
			
			feed.Link			=  dr["Link"] as string;				
			
			if (dr["SubscribeDate"] != DBNull.Value)
				feed.SubscribeDate	= (DateTime) dr["SubscribeDate"];				
			
			feed.ETag			= dr["Etag"] as string;				
			
			feed.LastModified	= (DateTime)dr["LastModified"];
			
			feed.Title			=  dr["Title"] as string;
			
			feed.Url			= (string) dr["Url"] as string;				

			if (dr["FolderFeedId"] != null && dr["FolderFeedId"] != DBNull.Value)
				feed.FolderFeedId	= (int) dr["FolderFeedId"];
			
			if (dr["UnreadCount"] != null)
				feed.UnreadCount	= (int) dr["UnreadCount"];
			
			return feed;
		}

		public static FeedPost PopulateRollerFeedPostFromIDataReader(IDataReader dr, DateTime lastReadPostDate)
		{
			FeedPost post = new FeedPost();

			post.FeedPostId			= (int) dr["FeedPostId"];
			post.FeedId				= (int) dr["FeedId"];
		
			if (dr["FeedTitle"] != DBNull.Value)
				post.FeedTitle = (string) dr["FeedTitle"];

			if (dr["FeedLink"] != DBNull.Value)
				post.FeedLink = (string) dr["FeedLink"];

			if (dr["Author"] != DBNull.Value)
				post.Author = (string) dr["Author"];

			if (dr["Title"] != DBNull.Value)
				post.Title = (string) dr["Title"];

			if (dr["Description"] != DBNull.Value)
				post.Description = (string) dr["Description"];

			if (dr["Source"] != DBNull.Value)
				post.Source = (string) dr["Source"];

			if (dr["GuidName"] != DBNull.Value)
				post.GuidName = (string) dr["GuidName"];

			if (dr["GuidIsPermaLink"] != DBNull.Value)
				post.GuidIsPermaLink = Convert.ToBoolean(dr["GuidIsPermaLink"].ToString());

			if (dr["Link"] != DBNull.Value)
				post.Link = (string) dr["Link"];

			if (dr["PubDate"] != DBNull.Value)
				post.PubDate = DateTime.Parse(dr["PubDate"].ToString());

			if (dr["CommentsUrl"] != DBNull.Value)
				post.CommentsUrl = (string) dr["CommentsUrl"];

			if (dr["EnclosureUrl"] != DBNull.Value)
				post.EnclosureUrl = (string) dr["EnclosureUrl"];

			if (dr["EnclosureLength"] != DBNull.Value)
				post.EnclosureLength = (long) dr["EnclosureLength"];

			if (dr["EnclosureType"] != DBNull.Value)
				post.EnclosureType = (string) dr["EnclosureType"];

			if (dr["Creator"] != DBNull.Value)
				post.Creator = (string) dr["Creator"];

			if (dr["CommentApiUrl"] != DBNull.Value)
				post.CommentApiUrl = (string) dr["CommentApiUrl"];

			if (dr["CommentRssUrl"] != DBNull.Value)
				post.CommentRssUrl = (string) dr["CommentRssUrl"];

			if (dr["CommentCount"] != DBNull.Value)
				post.CommentCount = (int) dr["CommentCount"];


			return post;
		}


		public static FeedPost PopulateFeedPostFromIDataReader(IDataReader dr, DateTime lastReadPostDate)
		{
			FeedPost post = new FeedPost();

			post.FeedPostId			= (int) dr["FeedPostId"];
			post.FeedId				= (int) dr["FeedId"];
		
			if (dr["Author"] != DBNull.Value)
				post.Author = (string) dr["Author"];

			if (dr["Title"] != DBNull.Value)
				post.Title = (string) dr["Title"];

			if (dr["Description"] != DBNull.Value)
				post.Description = (string) dr["Description"];

			if (dr["Source"] != DBNull.Value)
				post.Source = (string) dr["Source"];

			if (dr["GuidName"] != DBNull.Value)
				post.GuidName = (string) dr["GuidName"];

			if (dr["GuidIsPermaLink"] != DBNull.Value)
				post.GuidIsPermaLink = Convert.ToBoolean(dr["GuidIsPermaLink"].ToString());

			if (dr["Link"] != DBNull.Value)
				post.Link = (string) dr["Link"];

			if (dr["PubDate"] != DBNull.Value)
				post.PubDate = DateTime.Parse(dr["PubDate"].ToString());

			if (dr["CommentsUrl"] != DBNull.Value)
				post.CommentsUrl = (string) dr["CommentsUrl"];

			if (dr["EnclosureUrl"] != DBNull.Value)
				post.EnclosureUrl = (string) dr["EnclosureUrl"];

			if (dr["EnclosureLength"] != DBNull.Value)
				post.EnclosureLength = (long) dr["EnclosureLength"];

			if (dr["EnclosureType"] != DBNull.Value)
				post.EnclosureType = (string) dr["EnclosureType"];

			if (dr["Creator"] != DBNull.Value)
				post.Creator = (string) dr["Creator"];

			if (dr["CommentApiUrl"] != DBNull.Value)
				post.CommentApiUrl = (string) dr["CommentApiUrl"];

			if (dr["CommentRssUrl"] != DBNull.Value)
				post.CommentRssUrl = (string) dr["CommentRssUrl"];

			if (dr["CommentCount"] != DBNull.Value)
				post.CommentCount = (int) dr["CommentCount"];

			try
			{
				if (dr["HasRead"] != DBNull.Value)
				{	
					string hasRead = dr["HasRead"].ToString();
					post.HasRead = (hasRead == "1" ? true : false);
				}
				
			}
			catch (IndexOutOfRangeException) {}
//
//			try
//			{
//				if (dr["LastReadPostDate"] != DBNull.Value)
//					post.LastReadPostDate = DateTime.Parse(dr["LastReadPostDate"].ToString());
//			}
//			catch (IndexOutOfRangeException)
//			{
//				// Eat this exception in the case where the column is not there.
//			}
//
//			try
//			{
//				if (dr["FeedTitle"] != DBNull.Value)
//					post.FeedTitle = dr["FeedTitle"].ToString();
//			}
//			catch (IndexOutOfRangeException) {}
//
//			try
//			{
//				if (dr["FeedLink"] != DBNull.Value)
//					post.FeedLink = dr["FeedLink"].ToString();
//			}
//			catch (IndexOutOfRangeException) {}


			return post;
		}

		public static Folder PopulateFolderFromIDataReader(IDataReader dr)
		{
			Folder folder = new Folder();


			folder.FolderId = (int) dr["FolderId"];

			folder.UserId = (int) dr["UserId"];

			if (dr["FolderName"] != DBNull.Value)
				folder.FolderName = (string) dr["FolderName"];

			try
			{
				if (dr["UnreadCount"] != DBNull.Value)
					folder.UnreadCount = (int) dr["UnreadCount"];
				
			}
			catch (Exception){}

			return folder;
		}
		
		public static OpmlOutline PopulateOpmlOutlineFromIDataReader(IDataReader dr)
		{
			OpmlOutline outline = new OpmlOutline();


			if (dr["FolderName"] != DBNull.Value)
				outline.FolderName = (string) dr["FolderName"];

			if (dr["Title"] != DBNull.Value)
				outline.Title = (string) dr["Title"];

			if (dr["Url"] != DBNull.Value)
				outline.Url = (string) dr["Url"];

			if (dr["Link"] != DBNull.Value)
				outline.Link = (string) dr["Link"];


			return outline;
		}
		#endregion

		#region Helpers

		public static FeedState ResolveFeedState(int feedStateId)
		{
			FeedState state; 

			switch (feedStateId)
			{
				case 0:
					state = FeedState.UpdateSuccessful;
					break;
				case 1:
					state = FeedState.FeedNotFound;
					break;
				case 2: 
					state = FeedState.UnknownError;
					break;
				case 3:
					state = FeedState.InvalidFormat;
					break;
                case 4:
                    state = FeedState.FeedCached;
                    break;
				case 5:
					state = FeedState.AmbiguousRedirect;
					break;
				default:
					state = FeedState.UnknownError;
					break;
			}

			return state;
		}

		public static int ResolveFeedStateId(FeedState feedState)
		{
			return (int) feedState;
		}

		#endregion


	}
}
