using System;
using System.Collections.Generic;
using System.Globalization;
using System.Threading;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using TABS.MailCarrier.WebSDK;
using TABS.MailCarrier.WebSDK.Board;
using TABS.MailCarrier.WebSDK.User;

/// <summary>
/// New.aspx 파라미터 
///   action (필수) - new, reply, modify
///   board (필수, GUID) - 게시판 ID
///   article (선택, int) - reply/modify에서 게시글 ID
///   page (선택, int) - 페이지 번호(0에서 시작)
///   searchCategoty (선택) - 검색 카테고리(subject, author, content)
///   searchKeyword (선택) - 검색 키워드 
/// </summary>
public partial class Board_New : System.Web.UI.Page
{
    [Serializable]
    public class AttachmentEx : Attachment
    {
        public bool NewAttach { get; set; }
        public bool Deleted { get; set; }

        /// <summary>
        /// 새 첨부 파일 추가
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="filePath"></param>
        public AttachmentEx(string fileName, string filePath) : base(fileName, filePath)
        {
            NewAttach = true;
            Deleted = false;
        }

        /// <summary>
        /// 편집 모드로 파일 로딩
        /// </summary>
        /// <param name="fileId"></param>
        public AttachmentEx(Guid fileId) : base(fileId)
        {
            NewAttach = false;
            Deleted = false;
        }
    }

    [Serializable]
    public class AttachmentExCollection : List<AttachmentEx>
    {
    }

    protected string _action;
    protected Guid _boardId;
    protected int _articleId;
    protected string _page;
    protected string _searchCategoty;
    protected string _searchKeyword;
    protected string _listPageParams1;
    protected string _listPageParams2;

    protected Guid _uploadKey;                  // 업로드 정보(세션저장)를 구분하는 키
    private AttachmentExCollection _attachments = null;   // 첨부 파일 목록: ViewState에 저장

    protected override void InitializeCulture()
    {
        string defLang = WebUser.CurrentUser.UiLanguage;
        Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(defLang);
        Thread.CurrentThread.CurrentUICulture = new CultureInfo(defLang);
        base.InitializeCulture();
    }

    protected void Page_Init(object sender, EventArgs e)
    {
        WebUtil.SetMcCommonCss(Page.Header);
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        _action = WebParam.GetStrParamValue("action");
        _boardId = WebParam.GetGuidParamValue("board");
        _articleId = WebParam.GetIntParamValue("article");
        _page = WebParam.GetStrParamValue("page");
        _searchCategoty = WebParam.GetStrParamValue("searchCategoty");
        _searchKeyword = WebParam.GetStrParamValue("searchKeyword");
        _listPageParams1 = string.Format("board={0}", _boardId);
        _listPageParams2 = string.Format("board={0}&page={1}&searchCategoty={2}&searchKeyword={3}", _boardId, _page, _searchCategoty, Server.UrlEncode(_searchKeyword));
        Page.Title = AppSetting.GetTitleInfo(Request).Title;

        if (!IsPostBack)
        {
            _uploadKey = Guid.NewGuid();
            _attachments = new AttachmentExCollection();

            Board.RsAccessFlag accessFlag = Board.GetAccessFlag(WebUser.CurrentUser.DomainUserID, _boardId);
            if ((accessFlag & (Board.RsAccessFlag.Write | Board.RsAccessFlag.Admin)) <= 0 || !AppSetting.PassDisplayBoardFilter(_boardId, WebUser.CurrentUser.MailAddress))
            {
                // 게시판에 글을 게시할 권한이 없습니다.
                Response.Redirect("~/Error.aspx?code=15", true);
                return;
            }
            if (CheckPermitSize(_boardId))
            {
                // 지정된 게시판의 용량이 초과하여 더이상 글을 쓸 수 없습니다.
                Response.Redirect("~/Error.aspx?code=16", true);
                return;
            }

            if (_action == "new")
            {
                InitNewArticle();
            }
            else if (_action == "reply")
            {
                InitReplyArticle();                
                BootstrapUtil.CollapseControl(fixedTopPanel, true);
            }
            else if (_action == "modify")
            {
                Article article = new Article(_articleId);
                article.Load();
                // 글 작성자 본인(쓰기 권한 필요) 및 관리자만 글을 수정할 수 있다.
                if (!(article.AuthorID == WebUser.CurrentUser.UserAccount || (accessFlag & Board.RsAccessFlag.Admin) > 0))
                {
                    Response.Redirect("~/Error.aspx?code=18", true);
                    return;
                }
                bool parentArticle = (article.Depth == 0);
                LoadModifyArticle(article);
                FixedTopCheckBox.Checked = (article.Flag & Article.AttrFlag.FixedTop) > 0;
                BootstrapUtil.CollapseControl(fixedTopPanel, !parentArticle);
            }
            if ((accessFlag & Board.RsAccessFlag.Admin) == 0)
            {                
                BootstrapUtil.CollapseControl(fixedTopPanel, true);
            }            

            ViewState["_uploadKey"] = _uploadKey;
            ViewState["_attachments"] = _attachments;            
        }
        else
        {
            _uploadKey = (Guid)ViewState["_uploadKey"];
            _attachments = (AttachmentExCollection)ViewState["_attachments"];            
        }
    }

    #region ASP.NET Event Handlers

    protected void SaveButton_Click(object sender, EventArgs e)
    {
        // 글 저장/수정 시에도 권한 검사를 진행한다.
        Board.RsAccessFlag accessFlag = Board.RsAccessFlag.None;
        if (_action == "new")
        {
            accessFlag = Board.GetAccessFlag(WebUser.CurrentUser.DomainUserID, _boardId);
            if ((accessFlag & (Board.RsAccessFlag.Write | Board.RsAccessFlag.Admin)) <= 0)
            {
                // 게시판에 글을 게시할 권한이 없습니다.
                Response.Redirect("~/Error.aspx?code=15", true);
                return;
            }
            Board board = new Board(_boardId);
            Article article = new Article();
            article.AuthorID = WebUser.CurrentUser.UserAccount;
            article.AuthorName = AuthorTextBox.Value;
            article.Subject = SubjectTextBox.Value;
            article.Body = WebUtil.GetFormattedPlainText(MsgTextBox.Value, true);
            if (FixedTopCheckBox.Checked) article.Flag = Article.AttrFlag.FixedTop;

            board.WebsiteAppUrl = WebParam.GetCurrentWebAppUrl();
            board.WebsiteAppUrl1 = AppSetting.GetTitleInfo(Request)["website1"];
            board.AddArticle(article, GetAttachments(), AppSetting.NewArticleNotificationTemplateFile);
            WebOperationLog.Write(WebUser.CurrentUser.MailAddress, Request.UserHostAddress, "M/Board/New.aspx", "Add", string.Format("BID:{0}, AID:{1}, S:{2}", _boardId.ToString(), article.ID, article.Subject));
            Response.Redirect("List.aspx?" + _listPageParams1);
        }
        else if (_action == "reply")
        {
            Article dummyArticle = new Article(_articleId);
            dummyArticle.Load();
            accessFlag = Board.GetAccessFlag(WebUser.CurrentUser.DomainUserID, dummyArticle.BoardID);
            if ((accessFlag & (Board.RsAccessFlag.Write | Board.RsAccessFlag.Admin)) <= 0)
            {
                // 게시판에 글을 게시할 권한이 없습니다.
                Response.Redirect("~/Error.aspx?code=15", true);
                return;
            }
            Board board = new Board(_boardId);
            Article article = new Article();
            article.AuthorID = WebUser.CurrentUser.UserAccount;
            article.AuthorName = AuthorTextBox.Value;
            article.Subject = SubjectTextBox.Value;
            article.Body = WebUtil.GetFormattedPlainText(MsgTextBox.Value, true);

            board.WebsiteAppUrl = WebParam.GetCurrentWebAppUrl();
            board.WebsiteAppUrl1 = AppSetting.GetTitleInfo(Request)["website1"];
            board.AddReplyArticle(_articleId, article, GetAttachments(), AppSetting.NewArticleNotificationTemplateFile);
            WebOperationLog.Write(WebUser.CurrentUser.MailAddress, Request.UserHostAddress, "M/Board/New.aspx", "Reply", string.Format("BID:{0}, AID:{1}, S:{2}", _boardId.ToString(), article.ID, article.Subject));
            Response.Redirect("List.aspx?" + _listPageParams2);
        }
        else if (_action == "modify")
        {
            Article dummyArticle = new Article(_articleId);
            dummyArticle.Load();
            accessFlag = Board.GetAccessFlag(WebUser.CurrentUser.DomainUserID, dummyArticle.BoardID);
            // 글 작성자 본인(쓰기 권한 필요) 및 관리자만 글을 수정할 수 있다.
            if (!(((accessFlag & Board.RsAccessFlag.Write) > 0 && dummyArticle.AuthorID == WebUser.CurrentUser.UserAccount) || (accessFlag & Board.RsAccessFlag.Admin) > 0))
            {
                // 게시판에 글을 게시할 권한이 없습니다.
                Response.Redirect("~/Error.aspx?code=15", true);
                return;
            }
            Article article = new Article(_articleId);
            article.AuthorName = AuthorTextBox.Value;
            article.Subject = SubjectTextBox.Value;
            article.Body = WebUtil.GetFormattedPlainText(MsgTextBox.Value, true);
            if (FixedTopCheckBox.Checked) article.Flag = Article.AttrFlag.FixedTop;

            Attachment[] added;
            Attachment[] removed;
            GetAddedRemovedAttachments(out added, out removed);
            article.Update(added, removed);
            WebOperationLog.Write(WebUser.CurrentUser.MailAddress, Request.UserHostAddress, "M/Board/New.aspx", "Modify", string.Format("BID:{0}, AID:{1}, S:{2}", dummyArticle.BoardID.ToString(), article.ID, article.Subject));

            Response.Redirect("List.aspx?" + _listPageParams2);
        }
    }

    protected void AddAttachFileButton_Click(object sender, EventArgs e)
    {
        UploadResultList results = (UploadResultList)Session[_uploadKey.ToString()];
        if (results == null) return;

        ExtIconMap iconMap = new ExtIconMap();
        long currentSize = GetCurrentTotalAttachSize();
        foreach (UploadResult result in results)
        {
            if (!result.Infected)
            {
                long totalSize = currentSize + result.FileSize;
                if (totalSize > AppSetting.MaxBoardAttachSize)
                {
                    // 첨부하려는 용량이 {0}를 초과하여 첨부할 수 없습니다.
                    string errMsg = string.Format(GetLocalResourceObject("Msg04").ToString(), WebUtil.GetFormattedFileSize(AppSetting.MaxBoardAttachSize));
                    ScriptManager.RegisterClientScriptBlock(this, Page.GetType(), "ShowWarning", string.Format("ShowMessage('{0}');", errMsg), true);
                    break;
                }
                else
                {
                    AttachmentEx attach = new AttachmentEx(result.FileName, result.FilePath);
                    _attachments.Add(attach);
                }
            }
        }

        ViewState["_attachments"] = _attachments;
        int attachCount = BindAttachmentsInfo();
        if (attachCount > 0) BootstrapUtil.CollapseControl(attachList, false);        // 첨부 파일이 있을 경우 숨김 해제
    }

    protected void RemoveAttachFileButton_Click(object sender, EventArgs e)
    {
        int index = int.Parse(RemoveAttachFileIndex.Value);
        _attachments[index].Deleted = true;
        ViewState["_attachments"] = _attachments;
        int attachCount = BindAttachmentsInfo();
        if (attachCount > 0) BootstrapUtil.CollapseControl(attachList, false);        // 첨부 파일이 있을 경우 숨김 해제
    }

    #endregion

    #region New, Reply and Modify

    private void InitNewArticle()
    {
        AuthorTextBox.Value = WebUser.CurrentUser.Name;
    }

    private void InitReplyArticle()
    {
        Article article = new Article(_articleId);
        article.Load();

        SubjectTextBox.Value = article.Subject;
        AuthorTextBox.Value = WebUser.CurrentUser.Name;
        MsgBodyHolder.Controls.Add(new LiteralControl(article.Body));
        SrcArticleView.Style["display"] = "inherit";
    }

    private void LoadModifyArticle(Article article)
    {
        SubjectTextBox.Value = article.Subject;
        AuthorTextBox.Value = article.AuthorName;
        MsgTextBox.Value = WebUtil.GetStrippedHtml(article.Body, true);
        foreach (Attachment attach in article.Attachments)
        {
            _attachments.Add(new AttachmentEx(attach.ID));
        }
        int attachCount = BindAttachmentsInfo();
        if (attachCount > 0) BootstrapUtil.CollapseControl(attachList, false);        // 첨부 파일이 있을 경우 숨김 해제
    }

    private Attachment[] GetAttachments()
    {
        List<Attachment> addedList = new List<Attachment>();
        foreach (AttachmentEx item in _attachments)
        {
            if (!item.Deleted)
            {
                if (item.Type == Attachment.AttachType.Inline)
                    addedList.Add(new Attachment(item.ID, item.FileName, item.FilePath));
                else
                    addedList.Add(new Attachment(item.FileName, item.FilePath));
            }
        }
        return (Attachment[])addedList.ToArray();
    }

    private void GetAddedRemovedAttachments(out Attachment[] added, out Attachment[] removed)
    {
        added = null;
        removed = null;

        List<Attachment> addedList = new List<Attachment>();
        foreach (AttachmentEx item in _attachments)
        {
            if (!item.Deleted && item.NewAttach)
            {
                if (item.Type == Attachment.AttachType.Inline)
                    addedList.Add(new Attachment(item.ID, item.FileName, item.FilePath));
                else
                    addedList.Add(new Attachment(item.FileName, item.FilePath));
            }
        }
        added = (Attachment[])addedList.ToArray();

        List<Attachment> removedList = new List<Attachment>();
        foreach (AttachmentEx item in _attachments)
        {
            if (item.Deleted) removedList.Add(new Attachment(item.ID));
        }
        removed = (Attachment[])removedList.ToArray();        
    }

    #endregion

    #region Internal Support Methods

    private long GetCurrentTotalAttachSize()
    {
        long totalSize = 0;
        foreach (AttachmentEx attach in _attachments)
        {
            if (!attach.Deleted) totalSize += attach.Size;
        }
        return totalSize;
    }

    private int BindAttachmentsInfo()
    {
        int attachCount = 0;
        long attachSize = 0;
        ExtIconMap iconMap = new ExtIconMap();
        StringBuilder attachSb = new StringBuilder();
        for (int i = 0; i < _attachments.Count; i++)
        {
            AttachmentEx attach = _attachments[i];
            if (!attach.Deleted)
            {
                string fileName = (attach.Type == Attachment.AttachType.Inline) ? "InlineImage" : attach.FileName;
                attachSb.Append(string.Format("<li class='list-group-item'><img src='../Images/Ext/{0}'/>{1} ({2}) <span class='fa-solid fa-xmark mc-likeLink' onclick=\"RemoveFile({3})\"></span></li>",
                    iconMap.GetIconName(attach.FilePath), fileName, WebUtil.GetFormattedFileSize(attach.Size), i));
                attachSize += attach.Size;
                attachCount++;
            }
        }
        AttachListTag.Text = attachSb.ToString();
        AttachSummaryLabel.Text = string.Format("{0}개 ({1})", attachCount, WebUtil.GetFormattedFileSize(attachSize));
        return attachCount;
    }

    private bool CheckPermitSize(Guid boardId)
    {
        long spaceAllowed, spaceUsed;

        UserBoard.GetSpaceInfo(WebUser.CurrentUser.DomainID, out spaceAllowed, out spaceUsed);
        if (spaceAllowed != -1 && spaceAllowed < spaceUsed)
        {
            return true;
        }
        return false;
    }

    #endregion
}