using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace BookDemo.QA
{
    public partial class Question : System.Web.UI.Page
    {
        BookDemoEntities ctx = new BookDemoEntities();
        private bool ownQuestion = false;//是否为自己提出的提问
        private QAQuestion question;//当前提问
        private int questionId = 0;
        /// <summary>
        /// 搜索关键字
        /// </summary>
        public string KeyWord { get; set; }

protected void Page_Load(object sender, EventArgs e)
{
    int.TryParse(Request.QueryString["id"], out questionId);//TODO:这里可以对id做一些验证判断

    /*过滤提问ID，特别是questionId=0的情况，虽然在缓存中存在，但是是全局的信息，
     *不是真实的提问信息*/
    if (questionId<=0)
    {
        Response.Write("找不到ID对应的提问");
        Response.End();
    }

            if (!IsPostBack)
            {
                if (!string.IsNullOrEmpty(Request.QueryString["kw"]))
                {
                    KeyWord = Server.UrlDecode(Request.QueryString["kw"].Trim());
                    Master.Keyword = KeyWord;
                }
                LoadInfo();
            }
        }

        /// <summary>
        /// 载入问答的信息，包括提问内容，所属目录以及回答信息
        /// </summary>
        /// <param name="questionId"></param>
private void LoadInfo()
{
    #region 原始读取数据库方法
    //question = ctx.QAQuestion.Include("QAAnswer").Include("QAAnswer.QAUserInfo").Include("QACatalog").Include("QAUserInfo").First(q => q.Id == questionId);
    #endregion
    
    #region 从缓存中读取
    QuestionAndAnswersCache qaCache = new QuestionAndAnswersCache();
    QuestionAndAnswers qa = qaCache.GetQuestionAndAnswersItem(questionId);
    if (qa == null)
    {
        Response.Write("找不到ID对应的提问");
        Response.End();
    }

    question = qa.Question;
    #endregion

            if (!string.IsNullOrEmpty(Common.GetUserName()) && question.QAUserInfo.UserName == Common.GetUserName())
            {
                ownQuestion = true;//如果当前用户的用户名和提问用户名相同，则当前用户就是此提问的“主人”，将有权利处理该提问的事务
            }

            //提问信息
            lblTitle.Text = question.Title.HighlightKeywords(KeyWord);//标题，关键字高亮
            lblText.Text = question.Text.HighlightKeywords(KeyWord);//提问内容，关键字高亮
            lblUserName.Text = question.QAUserInfo.UserName;//链表查询用户名
            lblCatalogName.Text = question.QACatalog.Name;//链表查询目录名

            //最佳答案
            if (question.State == 1)
            {
                panBestAnswer.Visible = true;//提问已解决，显示最佳答案
                QAAnswer bestAnswer = question.QAAnswer.First(a => a.BestAnswer == true);//找出最佳答案
                lblBestAnswerText.Text = bestAnswer.Text.HighlightKeywords(KeyWord);//最佳回答内容，关键字高亮
                lblBestAnswerPostDateTime.Text = bestAnswer.PostDatetime.ToString();//最佳回答发布时间
                lblBestAnswerUserName.Text = bestAnswer.QAUserInfo.UserName;//最佳回答用户
            }

            //绑定回答列表
            rptAnswers.DataSource = question.QAAnswer.Where(a => !a.BestAnswer);//将非“最佳答案”绑定到回答列表上
            rptAnswers.DataBind();

            //回答区域
            panAnswer.Visible =
                question.State == 0
                && !string.IsNullOrEmpty(Common.GetUserName())
                && !ownQuestion;//只有未找到最佳答案，并且用户已登陆，并且非提问者本人，才能回答
        }

        private void UpdateCache()
        {
            QuestionAndAnswersCache qaCache = new QuestionAndAnswersCache();
            qaCache.UpdateQuestionAndAnswersItem(questionId);
        }

        protected void btnAnswer_Click(object sender, EventArgs e)
        {
            string userName = Common.GetUserName();//当前用户名
            int questionId = Convert.ToInt32(Request.QueryString["id"]);//当前提问Id

            //检查是否已经回答过，如果已回答过，不能重复回答
            /*PS:此判断也可以在页面初始化的时候执行，如果用户已经回答过，则回答框不显示，
                 但是为了防止网页信息不同步而导致的重复提交，此处仍旧应当做一下判断。*/
            int answered = ctx.QAAnswer.Count(a => a.QAQuestion.Id == questionId && a.QAUserInfo.UserName == userName);
            if (answered > 0)
            {
                //在客户端提示不能重复回答
                Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "script", "alert('你已经回答过，不能重复回答！')", true);
                return;
            }

            //构造回答实体内容
            QAAnswer answer = new QAAnswer
            {
                QAUserInfo = ctx.QAUserInfo.First(u => u.UserName == userName),//当前回答用户的信息
                QAQuestion = ctx.QAQuestion.First(q => q.Id == questionId),//找到对应提问
                BestAnswer = false,
                PostDatetime = DateTime.Now,
                Text = txtAnswer.Text.Trim().Replace("\r\n", "<br />"),//把TextBox中的换行符换成Html换行符
                VoteBad = 0,
                VoteNice = 0,
            };

            ctx.AddToQAAnswer(answer);//添加回答到数据库

            //用户回答计数增加
            QAUserInfo answerUserInfo = answer.QAUserInfo;//回答者实体
            answerUserInfo.AnswerCount++;

            ctx.SaveChanges();//保存更新

            //更新缓存
            UpdateCache();

            /**以下采用重新用Get方式返回（停留）在当前页面，而不是保持原状，
               是为了消除PostBack的状态，防止客户端浏览器刷新造成的重复提交。**/
            Response.Redirect(Request.Url.PathAndQuery);//Request.Url.PathAndQuery是一般情况下获取当前页面文件路径+参数的最好方式
        }

        protected void rptAnswers_ItemDataBound(object sender, RepeaterItemEventArgs e)
        {
            Button btnBestAnswer = (Button)e.Item.FindControl("btnBestAnswer");//找到当前绑定项中，Id为“btnBestAnswer”的Button，并获取他的实例
            Button btnCloseAnswer = (Button)e.Item.FindControl("btnCloseAnswer");//找到当前绑定项中，Id为“btnCloseAnswer”的Button，并获取他的实例

            if (ownQuestion && (question.State == 0))
            {
                //“设为最佳答案”和“关闭回答”按钮仅在提问未解决，并且为当前“主人”时显示
                btnBestAnswer.Visible = true;
                btnCloseAnswer.Visible = true;
            }
        }

        protected void rptAnswers_ItemCommand(object source, RepeaterCommandEventArgs e)
        {
            int answerId = Convert.ToInt32(e.CommandArgument);
            QAAnswer answer = ctx.QAAnswer.Include("QAUserInfo").First(a => a.Id == answerId);
            QAConfig config = ctx.QAConfig.FirstOrDefault();//获取全局设置
            switch (e.CommandName)
            {
                case "BestAnswer":
                    int questionId = Convert.ToInt32(Request.QueryString["id"]);
                    QAQuestion ques = ctx.QAQuestion.First(q => q.Id == questionId);
                    ques.State = 1;//设为“已解决”
                    answer.BestAnswer = true;//设为最佳答案
                    //获取最佳回答的用户信息
                    QAUserInfo answerUserInfo = answer.QAUserInfo;
                    answerUserInfo.AnswerAcceptCount++;//用户最佳答案计数加1
                    config.Unsolve--;//未解决问题数减少
                    config.Solved++;//已解决问题数增加
                    break;
                case "CloseAnswer":
                    ctx.DeleteObject(answer);//删除提问（也可以设置一个字段，使其“关闭”）
                    break;
                default:
                    break;
            }
            ctx.SaveChanges();//保存并执行所有数据库操作

            UpdateCache();//更新缓存

            LoadInfo();//刷新页面信息
        }
    }
}
