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

using CommunityServer;
using CommunityServer.Components;
using CommunityServer.Components.SearchBarrel;
using System.Collections;
using CommunityServer.Files.Components;

namespace CommunityServer.Components.SearchBarrel
{
	public class FileSearchJob : SearchJob
	{
		public FileSearchJob() { }

		public override void IndexPosts(int setSize, int settingsID)
		{
			PostSet postSet =  FileGalleryDataProvider.Instance().SearchReindexPosts(setSize , settingsID);

			foreach (Post post in postSet.Posts) 
			{
				Hashtable words = new Hashtable();
				int totalBodyWords = 0;

				Entry entry = post as Entry;
				if(entry != null)
				{
					// Username
					words = Index(entry.Username, words, WordLocation.Author, settingsID);

					// Subject
					words = Index(entry.Subject, words, WordLocation.Subject, settingsID);

					// Count the attachment filename with the subject, if it doesn't equal the subject
					if(entry.Subject != entry.AttachmentFilename)
						words = Index(entry.AttachmentFilename, words, WordLocation.Subject, settingsID);

					// Body
					words = Index(entry.Body, words, WordLocation.Body, settingsID);

					// Get a count of the total words in the body
					totalBodyWords = SearchTerms.CleanSearchTerms(post.Body).Length;
					InsertIntoSearchBarrel(words, post, settingsID, totalBodyWords);
				}

				EntryComment comment = post as EntryComment;
				if(comment != null)
				{
					// Username
					words = Index(comment.Username, words, WordLocation.Author, settingsID);

					// Comment body
					words = Index(comment.Body, words, WordLocation.Body, settingsID);

					// Get a count of the total words
					totalBodyWords = SearchTerms.CleanSearchTerms(post.Body).Length;
					InsertIntoSearchBarrel(words, post, settingsID, totalBodyWords);
				}
			}
		}

		protected override double CalculateWordRank(Word word, Post post, int totalBodyWords)
		{
			int wordOccurrence = 0;
			double replyWeight = 0;
			double wordCount = 0;
			double rating = 0;
			int totalRatings = 0;

			// Word weighting:
			// ============================
			// Word Occurence:      20
			// Replies:             20
			// Total words in post: 20
			// Word in Excerpt:      5
			// Word in Subject:     10
			// Rating:              15
			//                    ----
			// Max score:           90

			// Assign a score for how many times the word occurs in the post
			//
			wordOccurrence = word.Occurence * 2;
			if(wordOccurrence > 20)
				wordOccurrence = 20;

			// Calculate the score for replies
			//
			if((post.PostLevel == 1) && (post.Replies == 0)) 
				replyWeight = 0;  // A post with no replies
			else 
			{
				replyWeight = ( (post.PostLevel - (post.Replies * 0.01)) / (post.PostLevel + post.Replies) ) * 20f;

				// If less than 0, weighting is 0
				if(replyWeight < 0)
					replyWeight = 0;
			}

			// Calculate a score for the count of total words in the post
			//
			if (totalBodyWords > 65)
				wordCount = 20;
			else
				wordCount = (totalBodyWords / 65f) * 20f;

			// Calculate the score for the ratings
			//
			if(post is IThread) 
			{
				IThread thread = (IThread) post;

				// Handle ratings
				if(thread.TotalRatings > 0)
				{
					// 5 points for rating greater than 10 ratings
					if (thread.TotalRatings > 25)
						totalRatings = 5;
					else if (thread.TotalRatings > 20)
						totalRatings = 4;
					else if (thread.TotalRatings > 15)
						totalRatings = 3;
					else if (thread.TotalRatings > 10)
						totalRatings = 2;
					else
						totalRatings = 1;

					rating = (thread.RatingAverage * 2);
				}
			}

			// Calculate the final weight of the word
			//
			return (wordOccurrence + replyWeight + word.OccurenceWeight + wordCount + totalRatings + rating) / 75f;
		}
	}
}
