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

using System;
using System.Text;
using System.Web;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;

using CommunityServer.Components;
using CommunityServer.Controls;
using CommunityServer.Discussions.Components;

namespace CommunityServer.Discussions.Controls 
{

    // *********************************************************************
    //  PostFlatView
    //
    /// <summary>
    /// This server control is used to display top level threads. Note, a thread
    /// is a post with more information. The Thread class inherits from the Post
    /// class.
    /// </summary>
    /// 
    // ********************************************************************/
    public class PostFlatView : TemplatedWebControl 
    {

        CSContext csContext;
        ForumPost post;
        Forum forum;
        ForumPermission permission;
		Forum reportForum;
        User currentUser;
		Thread postThread;
        bool siteEnableUserPostingAsAnonymous = false;
        bool forumEnableUserPostingAsAnonymous = false;

        protected override void OnInit(EventArgs e) {

			if (SkinName == null)                
				ExternalSkinFileName = "View-PostFlatView.ascx";
			else 
				ExternalSkinFileName = SkinName;


            this.csContext = CSContext.Current;
            this.currentUser = csContext.User;
            this.post = Posts.GetPost( csContext.PostID, currentUser.UserID, true, true );

            // Are we looking up the forum by forum id or post id
            //
            if (csContext.SectionID > 0) 
            {
                forum = Forums.GetForum(csContext.SectionID, true, true);
            } 
            else if (csContext.PostID > 0) 
            {
                forum = Forums.GetForumByPostID(csContext.PostID, csContext.User.UserID, true );
            }

            if (forum == null) 
            {
                PermissionBase.RedirectOrExcpetion(CSExceptionType.SectionNotFound, csContext.SectionID.ToString());
            }

			if (forum.SectionID == 0) 
			{
				UserMessages.InvalidateMessageCount(currentUser.UserID);
			}
            else
			{
			    SearchFilters.SetFilters(forum,ForumGroups.GetForumGroup(forum.GroupID),Context);
			}
        
			//Get the report forum
			reportForum = Forums.GetReportedForum();

            // Get site and forum settings if users may post as anonymous.
            //
            siteEnableUserPostingAsAnonymous = ForumConfiguration.Instance().EnableUserPostingAsAnonymous;
            forumEnableUserPostingAsAnonymous = forum.EnableAnonymousPostingForUsers;

            permission = forum.ResolvePermission( currentUser ) as ForumPermission;

            if( !permission.Read )
				PermissionBase.RedirectOrExcpetion(CSExceptionType.AccessDenied);

            base.OnInit(e);
        }

        protected string BuildQuickReplyScript()
        {
            string url = ForumUrls.Instance().QuickReply;

            StringBuilder sb = new StringBuilder();
            sb.AppendFormat(@"<script type=""text/javascript"">{0}", Environment.NewLine);
            sb.AppendFormat(@"function showQuickReply(postID) {{{0}", Environment.NewLine);
            sb.AppendFormat(@" Telligent_Modal.Open('{0}'+postID,{1},{2},reLoadPage); {3}", url,600,400, Environment.NewLine);
            sb.AppendFormat(@"}}{0}", Environment.NewLine);

//            sb.Append("function reloadCallback(res){	if(shouldRefresh){refresh();}}");
//            sb.Append(Environment.NewLine);


            sb.Append("function reLoadPage(shouldRefresh){	if(shouldRefresh){refresh();}}");
            sb.Append(Environment.NewLine);

            sb.AppendFormat(@"</script>{0}", Environment.NewLine);
            return sb.ToString();
        }

		protected override void OnLoad(EventArgs e) 
		{
			AjaxManager.Register(this, "PostFlatViewAJAX", true, AjaxDebug.None);

			if ( !Page.IsPostBack || !EnableViewState ) 
			{
				DataBind();
			}
			JavaScript.RegisterRefresh(this.Page);
			JavaScript.RegisterToolTips(this.Page);
			Page.RegisterClientScriptBlock("QuickReply", BuildQuickReplyScript());
			base.OnLoad(e);
		}

		[AjaxMethod(IncludeControlValuesWithCallBack=false)]
		public void TogglePostStatus(int postID)
		{
			ForumPost post = Posts.GetPost(postID, csContext.User.UserID, false, false, false);
			post.PostStatus ^= PostStatus.IsAnswer;
			Posts.UpdatePost(post, csContext.User.UserID);
		}

        #region Child Controls

        Repeater postRepeater;
        ForumPager pager, pager2;
        RatePost rateThread;
        CurrentPage currentPage, currentPage2;
        RequiredFieldValidator postBodyValidator;
        ForumImageButton prevThread;
        ForumImageButton nextThread;
        Label forumName;
        Label postSubject;
        ForumImageButton newPostButtonUp;
        ForumImageButton newPostButtonDown;
        Label threadStats;
        PlaceHolder pagingArea, pagingArea2;
		DropDownList sortOrder;
		ITrackedThread trackingButton;
		ModerationContextMenu modContextMenu;
        //StatusDropDownList threadStatus;

        #endregion

        #region Skin

        protected override void AttachChildControls() 
        {

            postRepeater = (Repeater)FindControl( "PostRepeater" );
            pager = (ForumPager)FindControl( "Pager" );
			pager2 = (ForumPager) FindControl("Pager2");
            rateThread = (RatePost)FindControl( "RateThread" );
            currentPage = (CurrentPage)FindControl( "CurrentPage" );
			currentPage2 = (CurrentPage)FindControl("CurrentPage2");
            postBodyValidator = (RequiredFieldValidator)FindControl( "PostBodyValidator" );
            prevThread = (ForumImageButton)FindControl( "PrevThread" );
            nextThread = (ForumImageButton)FindControl( "NextThread" );
            forumName = (Label)FindControl( "ForumName" );
            postSubject = (Label)FindControl( "PostSubject" );
            newPostButtonUp = (ForumImageButton)FindControl("NewPostButtonUp");
            newPostButtonDown = (ForumImageButton)FindControl("NewPostButtonDown");
            threadStats = (Label)FindControl("ThreadStats");
            pagingArea = (PlaceHolder)FindControl( "PagingArea" );
			pagingArea2 = (PlaceHolder) FindControl("PagingArea2");
			sortOrder = (DropDownList)FindControl( "SortOrder" );
			trackingButton = FindControl( "TrackingButton" ) as ITrackedThread;
			modContextMenu = (ModerationContextMenu) FindControl ("ModerationContextMenu");

            InitializeChildControls();
        }

        private void InitializeChildControls() 
        {
			sortOrder.SelectedIndexChanged += new EventHandler(sortOrder_SelectedIndexChanged);

			// Read if they have a cookie for a custom sort order set
			if(Context.Request.Cookies["PostSortOrder" + csContext.PostID] != null)
                sortOrder.Items.FindByValue( Context.Request.Cookies["PostSortOrder" + csContext.PostID].Value ).Selected = true;
			else
				sortOrder.Items.FindByValue( ((int)this.currentUser.PostSortOrder).ToString() ).Selected = true;

            postRepeater.ItemDataBound += new RepeaterItemEventHandler(postRepeater_ItemDataBound);
        }


        #endregion

        #region Event Handlers

		private void ModerationMenu_PostModerateRefresh (object sender, EventArgs e)
		{
			Posts.ClearPosts(csContext.PostID, pager.PageIndex, pager.PageSize, 0, 0);
			HttpContext.Current.Response.Redirect(HttpContext.Current.Request.Url.ToString(), true);
		}

        public void ThreadStatus_Changed (object sender, ThreadStatusEventArgs e) {
            if (e.ThreadID <= 0)
                return;

            Threads.UpdateThreadStatus( e.ThreadID, e.Status );
        }

		private void sortOrder_SelectedIndexChanged(object sender, EventArgs e)
		{
			// Set a cookie to store their sort preference for this post until they close the browser
			HttpCookie cookie = new HttpCookie("PostSortOrder" + csContext.PostID, sortOrder.SelectedValue.ToString());
			cookie.Expires = DateTime.MinValue;
			Context.Response.Cookies.Set(cookie);
			Context.Response.Redirect(Context.Request.RawUrl);
		}

        #endregion

        #region DataBinding
        public override void DataBind() 
        {
            base.DataBind();

            #region prev/next thread navigation
			
			if (this.prevThread != null)
				prevThread.Post = post;

			if ( this.nextThread != null)
				nextThread.Post = post;

            #endregion

			// Get the post's thread
			postThread = Threads.GetThread( post.ThreadID );
			if (!postThread.IsApproved)
				throw new CSException(CSExceptionType.PostNotFound, "The post starter is not approved");

            if(postThread != null)
            {
                Head.AddSiteNameTitle(postThread.Subject,Context);
                if(this.forum.IsPrivate)
                {
                    UsersOnline.PrivateLocation();
                }
                else
                {
                    UsersOnline.SetLocation(postThread.Subject);
                }
            }
			if (rateThread != null)
			{
				rateThread.Post = this.post;
				rateThread.Thread = postThread;
                
				if (csContext.SiteSettings.SectionRatingType == SectionRatingType.ThreadRating)
					rateThread.Visible = true;
			}

			if (modContextMenu != null)
			{
				modContextMenu.Forum = forum;
				modContextMenu.PostModerateRefresh += new EventHandler(ModerationMenu_PostModerateRefresh);
			}

			if (forumName != null)
				forumName.Text = postThread.Subject;

			if (postSubject != null)
				postSubject.Text = post.Subject;

			if(trackingButton != null)
			{
				trackingButton.IsTracked = ThreadTracking.IsTracked(post.ThreadID,csContext.User.UserID);
				trackingButton.ThreadID = post.ThreadID;
			}

            // Get a populated thread set
            //
            PostSet postSet = Posts.GetPosts(csContext.PostID, pager.PageIndex, pager.PageSize, 0, Int32.Parse(sortOrder.SelectedValue), true);

            postRepeater.DataSource = postSet.Posts;
            postRepeater.DataBind();

            pager.TotalRecords = currentPage.TotalRecords = postSet.TotalRecords;
			pager.UrlPattern = ForumUrls.Instance().PostPagedRaw(csContext.PostID);
			if (pager2 != null)
			{
				pager2.PageIndex = pager.PageIndex;
				pager2.TotalRecords = pager.TotalRecords;
				pager2.UrlPattern = pager.UrlPattern;
			}

            currentPage.TotalPages = pager.CalculateTotalPages();
            currentPage.PageIndex = pager.PageIndex;
			if (currentPage2 != null)
			{
				currentPage2.TotalRecords = currentPage.TotalRecords;
				currentPage2.TotalPages = currentPage.TotalPages;
				currentPage2.PageIndex = pager.PageIndex;
			}

			if (pagingArea != null)
				pagingArea.Visible = ( currentPage.TotalPages > 1 );

			if (pagingArea2 != null)
				pagingArea2.Visible = (currentPage.TotalPages > 1);


            #region Post/Reply Permissions
				
            if (newPostButtonUp != null) 
            {
                newPostButtonUp.Visible = UserCanPost();
            }

            if (newPostButtonDown != null) 
            {
                newPostButtonDown.Visible = UserCanPost();
            }

            #endregion

            #region Post Stats

            string[] info = new string[3];

            if (threadStats != null) 
            {				
                // Quick access to the first post, and only access
                // data we have (no trips to the DP).
                //
                if (postSet.TotalRecords > 0)
                {
                    ForumPost topPost;
                    if (Int32.Parse(sortOrder.SelectedValue) == (int)SortOrder.Ascending)
                        topPost = (ForumPost) postSet.Posts[0];
                    else
                        topPost = (ForumPost) postSet.Posts[postSet.Posts.Count-1]; 
                                        
					info[0] = Formatter.FormatUsername(postThread.MostRecentPostAuthorID, postThread.MostRecentPostAuthor, false);
                    info[1] = Formatter.FormatAgoDate( postThread.ThreadDate );
                    info[2] = Convert.ToString( postSet.TotalRecords - 1 );
                }

                threadStats.Text = String.Format( ResourceManager.GetString("PostFlatView_BriefInfo"), info);
            }

            #endregion


        }

        private void postRepeater_ItemDataBound(Object sender, RepeaterItemEventArgs e) {
			if( e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem ) 
			{
				ForumPost post = e.Item.DataItem as ForumPost;

				User user = post.User;

				switch ( e.Item.ItemType ) 
				{
					case ListItemType.Item:
					case ListItemType.AlternatingItem:

						RatePost ratePost = (RatePost) e.Item.FindControl("RatePost");
						ForumImageButton replyButton = (ForumImageButton) e.Item.FindControl("ReplyButton");
						ForumImageButton quoteButton = (ForumImageButton) e.Item.FindControl("QuoteButton");
						ForumImageButton deleteButton = (ForumImageButton) e.Item.FindControl("DeleteButton");
						ForumImageButton editButton = (ForumImageButton) e.Item.FindControl("EditButton");
						ModerationPopupMenu modPopupMenu = (ModerationPopupMenu)e.Item.FindControl( "ModerationPopupMenu" );
						UserOnlineStatus onlineStatus = (UserOnlineStatus)e.Item.FindControl( "OnlineStatus" );
						UserAvatar avatar = (UserAvatar)e.Item.FindControl( "Avatar" );
						Literal username = (Literal)e.Item.FindControl( "Username" );
						PostIcons postIcon = (PostIcons)e.Item.FindControl( "PostIcon" );
						RoleIcons roleIcon = (RoleIcons)e.Item.FindControl( "RoleIcon" );
						UserAttribute joinedAttribute = (UserAttribute)e.Item.FindControl( "JoinedAttribute" );
						UserAttribute locationAttribute = (UserAttribute)e.Item.FindControl( "LocationAttribute" );
						UserAttribute postsAttribute = (UserAttribute)e.Item.FindControl( "PostsAttribute" );
						UserAttribute pointsAttribute = (UserAttribute)e.Item.FindControl( "PointsAttribute" );
						Literal emoticon = (Literal)e.Item.FindControl( "Emoticon" );
						Literal subject = (Literal)e.Item.FindControl( "Subject" );
						PostAttachment postAttachment = (PostAttachment)e.Item.FindControl( "PostAttachment" );
						PostView postView = (PostView)e.Item.FindControl( "PostView" );
						HtmlAnchor postAnchor = (HtmlAnchor)e.Item.FindControl( "PostAnchor" );
						PostImageButtons buttonsForPoster = (PostImageButtons)e.Item.FindControl( "ButtonsForPoster" );
						IText postPoints = TextControlHelper.Create(e.Item.FindControl( "PostPoints" ));
						IText postIPAddress =  TextControlHelper.Create(e.Item.FindControl( "PostIPAddress" ));
						HyperLink reportLink = (HyperLink)e.Item.FindControl( "ReportLink" );
						HyperLink quickReply = (HyperLink)e.Item.FindControl( "quickReplyLink" );
						Panel answerPanel = e.Item.FindControl("AnswerPanel") as Panel;
                        StatusDropDownList threadStatus = e.Item.FindControl( "ThreadStatus" ) as StatusDropDownList;
                        ResourceControl threadStatusLabel = e.Item.FindControl( "ThreadStatusLabel" ) as ResourceControl;
                        HtmlGenericControl PostViewWrapper = e.Item.FindControl("PostViewWrapper") as HtmlGenericControl;
						FavoritePopupMenu favoritePopupMenu = e.Item.FindControl("FavoritePopupMenu") as FavoritePopupMenu;
						ContactPopupMenu contactPopupMenu = e.Item.FindControl("ContactPopupMenu") as ContactPopupMenu;
						//HtmlGenericControl ForumPostTitleArea = e.Item.FindControl("ForumPostTitleArea") as HtmlGenericControl;
						Href postLink = e.Item.FindControl("PostLink") as Href;
						Href parentLink = e.Item.FindControl("ParentLink") as Href;
						ResourceControl replyToLabel = e.Item.FindControl("ReplyToLabel") as ResourceControl;
						InlineTagEditorPanel tagEditorPanel = e.Item.FindControl("InlineTagEditorPanel") as InlineTagEditorPanel;
						 

						Boolean userCanReply = UserCanReply();

						CSContext cntx = CSContext.Current;

						if (tagEditorPanel != null)
						{
							tagEditorPanel.PostID = post.PostID;
							tagEditorPanel.SelectedTags = post.Categories;
						}

						if(postLink != null)
						{
							postLink.NavigateUrl = ForumUrls.Instance().PostPermaLink(cntx.PostID, post.PostID);
							postLink.Text = post.PostID.ToString();
							if(post.PostLevel == 1)
							{
								postLink.ToolTip = String.Format(ResourceManager.GetString("PostView_PostLink_ThreadTitle"), post.PostID.ToString());
							}
							else
							{
								postLink.ToolTip = ResourceManager.GetString("PostView_PostLink_PostTitle");
							}
						}

						if(replyToLabel != null)
						{
							if(post.PostLevel > 1)
							{
								replyToLabel.Visible = true;
							}
							else
							{
								replyToLabel.Visible = false;
							}
						}

						if(parentLink != null && post.PostLevel > 1)
						{
							parentLink.NavigateUrl = ForumUrls.Instance().PostPermaLink(cntx.PostID, post.ParentID);
							parentLink.Text = post.ParentID.ToString();
							parentLink.ToolTip = ResourceManager.GetString("PostView_PostLink_PostTitle");
						}

						if (ratePost != null)
						{
							ratePost.Post = post;
							if (cntx.SiteSettings.SectionRatingType == SectionRatingType.PostRating)
								ratePost.Visible = true;
						}

						if (replyButton != null) 
						{
							replyButton.Post = post;
							replyButton.Visible = userCanReply;
						}

						if (quoteButton != null) 
						{
							quoteButton.Post = post;
							quoteButton.Visible = userCanReply;
						}

						if (deleteButton != null) 
						{
							deleteButton.Post = post;
							deleteButton.Visible = permission.Delete;
						}

						if (editButton != null) 
						{
							editButton.Post = post;
							editButton.Visible = permission.Edit && (!forum.IsModerated || (user.ModerationLevel == ModerationLevel.Unmoderated));
						}

						if (answerPanel != null)
						{
							bool isAnswer = (post.PostStatus & PostStatus.IsAnswer) == PostStatus.IsAnswer;

							bool available = (post.PostLevel > 1) &&
								ForumConfiguration.Instance().EnableThreadStatus &&
								forum.EnableThreadStatus;

							bool visible = permission.MarkAsAnswer ||
								(csContext.User.UserID == postThread.AuthorID && (!isAnswer));

							answerPanel.Visible = available && visible;
						}

                        if (threadStatus != null) {
                            // set it ready for postback
                            threadStatus.AutoPostBack = true;
                            threadStatus.StatusChanged += new ThreadStatusEventHandler( ThreadStatus_Changed );
                            threadStatus.ThreadID = post.ThreadID;

                            // Check if it is visible 
                            bool isVisible = ( (post.PostLevel == 1) &&
                                               ForumConfiguration.Instance().EnableThreadStatus &&
                                               forum.EnableThreadStatus &&
                                               (csContext.User.IsAdministrator || 
                                               (csContext.User.UserID == post.User.UserID) ||
											   (csContext.User.IsModerator)) 
                                             ) ? true : false;
                            
                            // Set controls if they are visible
                            threadStatus.Visible = isVisible;
                            threadStatusLabel.Visible = isVisible;

                            // Only if visible get thread details. Thas happens only one time per thread listing.
                            if (isVisible) {
                                if (postThread != null) {
                                    threadStatus.SelectedValue = postThread.Status;
                                }
                            }
                        }

						if (modPopupMenu != null)
						{
							modPopupMenu.Post = post;
							modPopupMenu.Forum = forum;

							modPopupMenu.PostModerateRefresh += new EventHandler(ModerationMenu_PostModerateRefresh);
						}

						if (favoritePopupMenu != null)
						{
							favoritePopupMenu.PostID = post.PostID;
							favoritePopupMenu.SectionID = forum.SectionID;
							favoritePopupMenu.UserID = post.User.UserID;
							favoritePopupMenu.ApplicationType = ApplicationType.Forum;
						}

						if (contactPopupMenu != null)
						{
							if(post.User.IsAnonymous)
								contactPopupMenu.Visible = false;
							else
								contactPopupMenu.User = post.User;
						}

						// Notice the following controls that the user should be seen as anonymous
						//
						bool showUserAsAnonymous = (post.IsAnonymousPost && siteEnableUserPostingAsAnonymous && forumEnableUserPostingAsAnonymous);

						if (onlineStatus != null) 
						{ 
							onlineStatus.User = user;
							onlineStatus.IsCloakedUser = showUserAsAnonymous;
						}

						if (avatar != null) 
						{
							avatar.User = user;
							avatar.IsCloakedUser = showUserAsAnonymous;
						}

						if (username != null)
						{
							if (post.PostShouldBeIgnored)
							{
								username.Text = Formatter.FormatUsername ( user.UserID, post.Username, true, false, true );
							}
							else
							{
								username.Text = Formatter.FormatUsername ( user.UserID, post.Username, showUserAsAnonymous );
							}
						}

						if (postIcon != null) 
						{
							postIcon.User = user;
							postIcon.IsCloakedUser = showUserAsAnonymous;
						}

						if (roleIcon != null) 
						{
							roleIcon.User = user;
							roleIcon.IsCloakedUser = showUserAsAnonymous;
						}

						if (joinedAttribute != null) 
						{
							joinedAttribute.User = user;
							joinedAttribute.IsCloakedUser = showUserAsAnonymous;
						}

						if (locationAttribute != null) 
						{
							locationAttribute.User = user;
							locationAttribute.IsCloakedUser = showUserAsAnonymous;
						}

						if (postsAttribute != null) 
						{
							postsAttribute.User = user;
							postsAttribute.IsCloakedUser = showUserAsAnonymous;
						}

						if (pointsAttribute != null)
						{
							pointsAttribute.User = user;
							pointsAttribute.IsCloakedUser = showUserAsAnonymous;
						}

						if (emoticon != null)
							emoticon.Text = Formatter.GetEmotionMarkup( post.EmoticonID );

						if (subject != null)
							subject.Text = post.Subject;
					
						if (postAttachment!= null)
							postAttachment.Post = post;

						if (postView != null)
							postView.Post = post;

                        if(quickReply != null)
                        {
							if(!post.IsLocked && !currentUser.IsAnonymous && userCanReply)
							{
								quickReply.NavigateUrl =  "javascript:" + "showQuickReply(" + post.PostID.ToString() + ")";
								quickReply.Attributes.Add("onclick", "showQuickReply(" + post.PostID.ToString() + ")");
								quickReply.Text = ResourceManager.GetString("QuickReply");
							}
							else
							{
								quickReply.Visible = false;
							}
                            //PostViewWrapper.Attributes.Add("ondblclick", "showQuickReply(" + post.PostID.ToString() + ")");
							//JavaScript.RegisterControlForToolTip(PostViewWrapper,string.Format(ResourceManager.GetString("QuickReply_Popup_Message"),post.User.DisplayName),150);
                        }

						if (postAnchor != null)
							postAnchor.Name = post.PostID.ToString();

						if (buttonsForPoster != null) 
						{
							buttonsForPoster.User = user;
							buttonsForPoster.IsCloakedUser = showUserAsAnonymous;
						}

						if (postPoints != null)
							postPoints.Text = Formatter.PostPoints( post );

						if (postIPAddress != null)
							postIPAddress.Text = Formatter.PostIPAddress( post );

						if ((reportLink != null) && (reportForum != null))
						{
							reportLink.Visible = !user.IsAnonymous;

							ForumUrls forumUrls = new ForumUrls();
							reportLink.NavigateUrl = forumUrls.Report(reportForum.SectionID)  + "&ReportPostID=" + post.PostID.ToString();
							reportLink.Text = ResourceManager.GetString("Report");
						}

						break;
				}
			}
        }

        private Boolean UserCanReply() 
        {
			if (currentUser.IsAnonymous)
				return true;
			
            Boolean permissionToReply = permission.Reply;
            Boolean anonUserCanPost = ( CSContext.Current.SiteSettings.EnableAnonymousUserPosting && forum.EnableAnonymousPosting );
            return ( permissionToReply && ( !currentUser.IsAnonymous || anonUserCanPost ) );
        }

        private Boolean UserCanPost() 
        {
			if (currentUser.IsAnonymous)
				return true;

            Boolean permissionToPost = permission.Post;
            Boolean anonUserCanPost = ( CSContext.Current.SiteSettings.EnableAnonymousUserPosting && forum.EnableAnonymousPosting );
            return ( permissionToPost && ( !currentUser.IsAnonymous || anonUserCanPost ) );
        }
		#endregion

	}
}
