$(function() {
    // 댓글입력 창 높이 자동조정
    $.each($('textarea[data-autoresize]'), function () {
        $(this).on('keyup input', function () {
            Comment.resizeTextarea(this);
        }).removeAttr('data-autoresize');
    });
});

const Comment =
{
    callback: "",
    listID: "commentList",
    writeID: "commentWrite",
    method: {write: "store", edit: "update", reply: "reply"},
    mode: "",
    code: "",
    bid: 0,
    pid: 0,
    cid: 0,
    uid: 0,
    total: 0,
    page: 0,
    perPage: 0,
    minLength: 0,
    maxLength: 0,
    listForm: null,
    writeForm: null,
    saveHtml: null,
    saveBefore: null,
    useEditor: false,
    queryString: null,
    tinymce: null,

    // 댓글 기본설정
    init: function(config)
    {
        if(!config.hasOwnProperty("code") && !config.hasOwnProperty("bid") && !config.hasOwnProperty("pid")) {
            return false;
        }

        this.code = config.code;
        this.bid = config.bid;
        this.pid = config.pid;
        this.callback = (BASE_URL + "/board/" + String(this.code) + "/" + String(this.pid) + "/comment");

        this.listForm = document.getElementById(this.listID);
        this.writeForm = document.getElementById(this.writeID);

        // 댓글 입력창
        let form = this.writeForm.getElementsByTagName("form")[0];
        this.minLength = Number(form.elements["min_length"].value);
        this.maxLength = Number(form.elements["max_length"].value);
        this.saveHtml = this.writeForm.innerHTML; // 댓글 입력 창 저장
    },

    // 초기화
    reset: function(form)
    {
        this.mode = "write";
        this.cid = 0;
        this.saveBefore = null;

        if (typeof form !== "undefined") {
            if(form.elements["mode"].value !== "write") {
                form.style.display = "none";
            }
            form.elements["mode"].value = "write";
            form.elements["bid"].value = "";
            form.elements["pid"].value = "";
            form.elements["cid"].value = "";
            form.elements["uid"].value = "";
            form.elements["length"].value = "0";
            form.elements["content"].value = "";
            if (form.elements.hasOwnProperty("username")) {
                form.elements["username"].value = "";
            }
            if (form.elements.hasOwnProperty("password")) {
                form.elements["password"].value = "";
            }
            if (form.elements.hasOwnProperty("is_secret")) {
                form.elements["is_secret"].checked = false;
            }
            let length = form.getElementsByClassName("comment-length");
            if (length.length > 0) {
                length[0].innerText = "0";
            }
            form.elements["btn_comment_submit"].disabled = false;
            form.elements["btn_comment_cancel"].disabled = false;
            this.resizeTextarea(form.elements["content"]);
        }

        if (this.useEditor) {
            tinyMCE.activeEditor.setContent("");
        }
    },

    // 댓글 목록 새로고침
    refresh: function() {
        this.list(this.page);
    },

    // textarea 높이 조절
    resizeTextarea: function(e)
    {
        $(e).css("height", "auto").css("height", e.scrollHeight + (e.offsetHeight - e.clientHeight));
    },

    // 댓글 영역으로 스크롤 이동
    scrollReplyNow: function(cid)
    {
        if (typeof cid != "undefined" && cid) {
            let offset = $("#comment_" + cid).offset();
            if (typeof offset != "undefined") {
                window.document.body.scrollTop = offset.top;
                document.getElementById("comment_" + cid).scrollIntoView();
            }
        }
    },

    // 댓글 영역 강조
    focusCommentBox: function(cid)
    {
        if (typeof cid != "undefined" && cid) {
            $("#comment_" + cid).effect("highlight", {
                'color': '#4f4f4f'
            }, 1500);
        }
    },

    // 금지 단어 확인
    filterSpamKeyword: function (content)
    {
        let ret = "";
        $.ajax({
            headers: {"X-CSRF-TOKEN": CSRF},
            url: (BASE_URL + "/api/filterSpamKeyword"),
            type: "post",
            dataType: "json",
            async: false,
            cache: false,
            data: {subject: "", content: content},
            success: function (res) {
                ret = res.content;
            },
            error: function (xhr, status, err) {
                procErrorEvent(xhr, status, err);
            }
        });
        return ret;
    },

    // 글자수 확인
    checkByte: function(e)
    {
        let form = e.form;

        if (typeof form !== "undefined") {
            let hiddenInputLength = form.elements["length"];
            let spanInputLength = form.getElementsByClassName("comment-length")[0];
            let textarea = form.elements["content"];
            let length = textarea.value.length;
            let tinymce = form.getElementsByTagName("iframe");

            if (this.useEditor) {
                let editor = tinymce[0].contentDocument.body;
                length = editor.innerText.trim().length;
                if (this.maxLength > 0 && length > this.maxLength) {
                    editor.innerHTML = editor.innerHTML.substr(0, this.maxLength);
                    length = editor.innerHTML.length;
                }
            } else {
                if (this.maxLength > 0 && length > this.maxLength) {
                    textarea.value = textarea.value.substr(0, this.maxLength);
                    length = textarea.value.length;
                }
            }

            // 글자 수 저장
            hiddenInputLength.value = length;

            // 글자 수 출력
            if (typeof spanInputLength !== "undefined") {
                spanInputLength.innerText = length;
            }
        }
    },

    // 목록
    list: function(page, cid, message, sort) {
        if(!this.code && !this.bid && !this.pid) {
            return false;
        }

        if (!page || page < 1 || page === Number.POSITIVE_INFINITY) {
            page = 1;
        }

        let listURL = (this.callback + "?page=" + page);
        if (sort) {
            listURL += "&sort=" + sort;
        }

        $('#' + this.listID).load(listURL, function (response, status, xhr) { // HTML 형식으로 뎃글목록 출력
            if(status !== "success") {
                return;
            }

            let total = this.children.total.value;
            let page = this.children.page.value;
            let perPage = this.children.per_page.value;

            document.getElementById("txtCommentRows").innerText = total;
            document.getElementById("txtPostCommentCnt").innerText = total;

            if (message) { // 알림이 있을 경우 alert
                alert(message);
            }

            Comment.total = total;
            Comment.page = page;
            Comment.perPage = perPage;
            Comment.focusCommentBox(cid);
            Comment.scrollReplyNow(cid);
        });
    },

    // 댓글 등록/수정
    submit: function(e)
    {
        e.blur();
        e.disabled = true;

        $(e.form).validate({
            onkeyup: false,
            onclick: false,
            onfocusout: false,
            rules: {
                username: {required: "#username:enabled", minlength: 2, maxlength: 10},
                password: {required: "#password:enabled", minlength: 3, maxlength: 10},
                mode: {required: true, contains: ["write", "edit", "reply"]},
                content: {
                    required: true,
                    normalizer: function (value) {
                        if(Comment.useEditor) {
                            return tinyMCE.activeEditor.getContent({format: "text"}).trim();
                        }else{
                            return value.trim();
                        }
                    },
                    minlength: Comment.minLength,
                    maxlength: function() {
                        return (Comment.maxLength > 0 ? Comment.maxLength : 500)
                    }
                },
                is_secret: {number: true}
            },
            messages: {
                username: {required: "이름을 입력하세요.", minlength: "이름은 두 글자 이상 입력하세요.", maxlength: "이름은 10자까지 입력 가능합니다."},
                password: {required: "비밀번호를 입력하세요.", minlength: "비밀번호는 3자 이상 입력하세요.", maxlength: "비밀번호는 10자까지 입력 가능합니다."},
                mode: {required: "댓글 처리중 오류가 발생하였습니다.", contains: "잘못된 요청입니다."},
                content: {required: "댓글을 입력해주세요."},
                is_secret: {number: true}
            },
            showErrors: function (errorMap, errorList) {
                if (this.numberOfInvalids()) {
                    setTimeout(function() {
                        alert(errorList[0].message);
                        errorList[0].element.focus();
                        if(Comment.useEditor) {
                            tinyMCE.activeEditor.getBody().scrollIntoView();
                        }else{
                            window.scrollTo({top: errorList[0].element.offsetTop});
                        }
                    }, 100);
                    e.disabled = false;
                }
            },
            submitHandler: function (form)
            {
                let formData = new FormData(form);
                let spamKeyword = Comment.filterSpamKeyword(formData.get("content")); // 금지 단어 검사
                if (spamKeyword) {
                    alert("내용에 금지어 ('" + spamKeyword + "')가 포함 되어있습니다.");
                    form.elements["content"].focus();
                    return false;
                }

                let page;
                let mode = formData.get("mode");
                if(mode === "write") {
                    formData.append("bid", Comment.bid);
                    formData.append("pid", Comment.pid);
                    page = Math.ceil((Number(Comment.total) + 1) / Comment.perPage);
                }else{
                    page = Comment.page;
                }

                if(mode === "edit") {
                    formData.append("_method", "PUT");
                }

                // 버튼 비활성화
                form.elements["btn_comment_submit"].disabled = true;
                form.elements["btn_comment_cancel"].disabled = true;

                $.ajax({
                    headers: {'X-CSRF-TOKEN': CSRF},
                    url: (Comment.callback + "/" + Comment.method[mode]),
                    type: "post",
                    cache: false,
                    async: true,
                    contentType: false,
                    processData: false,
                    data: formData,
                    dataType: "json",
                    beforeSend: function () {
                        if (formData.get("uid")) { // 권한 확인
                            if (!loginCheck()) {
                                return xhr.abort();
                            }
                        }
                        showLoading();
                    },
                    success: function (res) {
                        if (res.success) {
                            Comment.list(page, res.cid);
                        }else{
                            alert(res.message);
                        }
                    },
                    error: function (xhr, status, err) {
                        procErrorEvent(xhr, status, err);
                    },
                    complete: function() {
                        Comment.reset(form);
                        hideLoading();
                    }
                });
            }
        });

        $(e.form).submit();
    },

    // 수정, 답글
    write: function(e, mode)
    {
        e.blur();

        if(typeof e === "undefined") {
            return false;
        }
        if(typeof mode === "undefined" || mode == null || !mode) {
            return false;
        }
        if(!mode in this.method) {
            return false;
        }

        let formData = new FormData(e.form); // 댓글 영역
        let mediaFormID = ("#fCommentWrite_" + formData.get("cid")); // 현재 답글 번호
        let $saveBefore = $(this.saveBefore); // 이전 댓글 창
        let $target = $(mediaFormID); // 현재 댓글 창

        if(this.cid === formData.get("cid") && this.saveBefore === mediaFormID && this.mode === mode) {
            $saveBefore.toggle();
        }else{
            $saveBefore.html("");
            $target.show();

            let writeForm = $target.html(this.saveHtml).get(0).firstElementChild;

            // 답글
            if(mode === "reply") {
                if(writeForm.elements.hasOwnProperty("username")) {
                    writeForm.elements["username"].value = "";
                }
                if(writeForm.elements.hasOwnProperty("is_secret")) {
                    writeForm.elements["is_secret"].checked = false;
                }
                writeForm.elements["content"].value = "";
            }

            // 수정
            if(mode === "edit") {
                if(writeForm.elements.hasOwnProperty("username")) {
                    writeForm.elements["username"].value = formData.get("username");
                }
                if(writeForm.elements.hasOwnProperty("is_secret")) {
                    writeForm.elements["is_secret"].checked = Boolean(formData.get("is_secret").checked);
                }
                writeForm.elements["content"].value = formData.get("content");

                // 입력창 높이 조절
                this.resizeTextarea(writeForm.elements["content"]);
            }

            writeForm.elements["mode"].value = mode;
            writeForm.elements["bid"].value = formData.get("bid");
            writeForm.elements["pid"].value = formData.get("pid");
            writeForm.elements["cid"].value = formData.get("cid");
            writeForm.elements["uid"].value = formData.get("uid");

            // textarea ID 할당
            if(writeForm) {
                writeForm.elements["content"].setAttribute("id", formData.get("content") + "_" + formData.get("cid"));

                // 1:1 문의 게시판은 에디터를 사용
                if(this.useEditor) {
                    tinyMCE.EditorManager.execCommand('mceAddEditor', true, writeForm.elements["content"]);
                }

                // 글자 수 확인
                this.checkByte(formData.get("content"));
            }
        }

        this.mode = mode;
        this.cid = formData.get("cid");
        this.saveBefore = mediaFormID; // 현재 영역
    },

    // 댓글 삭제
    delete: function(e)
    {
        e.blur();

        let formData = new FormData(e.form);

        $.ajax({
            url: (this.callback + "/delete"),
            type: "delete",
            cache: false,
            async: false,
            data: {bid: formData.get("bid"), pid: formData.get("pid"), cid: formData.get("cid"), _method: "DELETE"},
            dataType: "json",
            beforeSend: function(xhr) {
                if (!formData.get("uid")) { // 권한 확인
                    const password = prompt("댓글 비밀번호 확인이 필요합니다.\n비밀번호를 입력해주세요.");
                    if (!password) {
                        return false;
                    }
                    this.url += ("?passwd=" + encodeURIComponent(password.trim()));
                } else {
                    if (!loginCheck()) {
                        return xhr.abort();
                    }
                }
                if (!confirm("댓글을 삭제하시겠습니까?")) {
                    return false;
                }
            },
            success: function (res) {
                if (res.success) {
                    alert("댓글이 삭제되었습니다.");
                    Comment.refresh();
                }else{
                    alert(res.message || "처리 중 오류가 발생하였습니다. 관리자에게 문의하십시오.");
                }
                Comment.reset();
            },
            error: function (xhr, status, err) {
                procErrorEvent(xhr, status, err);
            }
        });
        return false;
    },

    // 댓글 신고
    blame: function(e)
    {
        e.blur();

        if(!loginCheck()) {
            return false;
        }

        // 신고 접수 유효성 적용
        $("#fCommentBlame").validate({
            onkeyup: false,
            onclick: false,
            onfocusout: false,
            rules: {
                type: {required: true, contains: ['1', '2', '3', '4', '5', '6', '7', '8', '9']},
                reason: {
                    required: true, normalizer: function (value) {
                        return $.trim(value);
                    }, maxlength: 1000
                }
            },
            messages: {
                type: {required: "신고 유형을 선택해주세요.", contains: "잘못된 요청입니다."},
                reason: {required: "신고 내용을 입력해주세요.", maxlength: "신고 내용은 {0}자까지 입력 가능합니다."}
            },
            showErrors: function (errorMap, errorList) {
                if (this.numberOfInvalids()) {
                    alert(errorList[0].message);
                    errorList[0].element.focus();
                }
            },
            submitHandler: function (form) {
                if (confirm("신고를 접수하시겠습니까?")) {
                    let formData = new FormData(form);
                    formData.append("bid", e.form.elements["bid"].value);
                    formData.append("pid", e.form.elements["pid"].value);
                    formData.append("cid", e.form.elements["cid"].value);

                    $.ajax({
                        url: (Comment.callback + "/blame"),
                        type: "post",
                        cache: false,
                        contentType: false,
                        processData: false,
                        data: formData,
                        dataType: "json",
                        beforeSend: function (xhr) {
                            if (!loginCheck()) {
                                xhr.abort();
                            }
                        },
                        success: function (res) {
                            if (res.success) {
                                alert("감사합니다. 신고가 접수되었습니다. 이용 규칙을 위반한 것으로 확인되면 댓글이 삭제됩니다.");
                            } else {
                                alert(res.message || "처리 중 오류가 발생하였습니다. 관리자에게 문의하십시오.");
                            }
                        },
                        error: function (xhr, status, err) {
                            procErrorEvent(xhr, status, err);
                        },
                        complete : function() {
                            $("#commentBlameModal").modal('hide');
                        }
                    });
                }
            }
        });
    },

    // 추천
    like: function (e) {
        let formData = new FormData(e.form);
        formData.append("type", e.value);

        $.ajax({
            url: (this.callback + "/like"),
            type: "post",
            cache: false,
            contentType: false,
            processData: false,
            data: formData,
            dataType: "json",
            beforeSend: function (xhr) {
                if (!loginCheck()) {
                    xhr.abort();
                }
            },
            success: function (res) {
                if (res.success) {
                    Comment.toggleLike(formData.get("cid"), 1, !Number(e.dataset.active));
                } else {
                    alert(res.message || "처리 중 오류가 발생하였습니다. 관리자에게 문의하십시오.");
                }
            },
            error: function (xhr, status, err) {
                procErrorEvent(xhr, status, err);
            }
        });
    },

    // 비추천
    dislike: function (e) {
        let formData = new FormData(e.form);
        formData.append("type", e.value);

        $.ajax({
            url: (this.callback + "/dislike"),
            type: "post",
            cache: false,
            contentType: false,
            processData: false,
            data: formData,
            dataType: "json",
            beforeSend: function (xhr) {
                if (!loginCheck()) {
                    xhr.abort();
                }
            },
            success: function (res) {
                if (res.success) {
                    Comment.toggleLike(formData.get("cid"), 2, !Number(e.dataset.active));
                } else {
                    alert(res.message || "처리 중 오류가 발생하였습니다. 관리자에게 문의하십시오.");
                }
            },
            error: function (xhr, status, err) {
                procErrorEvent(xhr, status, err);
            }
        });
    },

    // 댓글 입력 취소
    cancel: function (e) {
        if (e.form.mode.value === "write") {
            e.form.elements["mode"].value = "write";
            e.form.elements["cid"].value = "";
            e.form.elements["length"].value = "0";
            e.form.elements["content"].value = "";
            if (typeof e.form.elements["is_secret"] !== "undefined") {
                e.form.elements["is_secret"].checked = false;
            }
            let length = e.form.getElementsByClassName("comment-length");
            if (length.length > 0) {
                length[0].innerText = "0";
            }
        } else {
            e.form.parentNode.style.display = "none";
            e.form.parentNode.innerHTML = "";
        }
        this.reset(e.form);
    },

    /*
     * 댓글 에디터 옵션 변경
     * 1:1 게시판에서 댓글을 작성하면 실행
     */
    setInitEditor: function () {
        let tinyMCEExtendSetting = {
            min_height: 210,
            max_height: 310,
            file_browser_url: (BASE_URL + "/board/" + this.code + "/uploader"),
            init_instance_callback: function (editor) {
                editor.on('SetContent', function (e) {
                    let iframeRows = e.target.contentDocument.body.getElementsByTagName("iframe");
                    if (iframeRows > 0) {
                        $(e.content).filter("iframe").attr("src", ""); // iframe src 주소
                    }
                });
                editor.on('keyup', function () {
                    Comment.checkByte(editor.targetElm);
                });
                editor.on('keypress', function () {
                    Comment.checkByte(editor.targetElm);
                    // document.getElementById(e.target.dataset.id).value = e.currentTarget.textContent;
                });
            }
        };

        this.tinymce = tinymce.init(Object.assign(tinyMCE.activeEditor.settings, tinyMCEExtendSetting));
        this.useEditor = true;
    },

    // 좋아요/싫어요 처리
    toggleLike: function (cid, type, active) {
        let btnCommentLike = document.getElementById("comment_" + cid).getElementsByClassName("btn-comment-like")[0];
        let btnCommentDisLike = document.getElementById("comment_" + cid).getElementsByClassName("btn-comment-dislike")[0];
        if (type === 1) {
            this.setLike(cid, active);
            if (Number(btnCommentDisLike.dataset.active)) {
                this.setDislike(cid, false);
            }
        } else if (type === 2) {
            this.setDislike(cid, active);
            if (Number(btnCommentLike.dataset.active)) {
                this.setLike(cid, false);
            }
        }
    },

    // 좋아요 갱신
    setLike: function (cid, active) {
        let button = document.getElementById("comment_" + cid).getElementsByClassName("btn-comment-like")[0];
        let rows = Number(button.dataset.rows);
        if (active) {
            rows = (rows + 1);
            button.innerHTML = '<i class="fas fa-thumbs-up"></i><span> ' + String(rows) + '</span>';
            button.dataset.active = "1";
        } else {
            rows = (rows > 0 ? rows - 1 : rows);
            button.innerHTML = '<i class="far fa-thumbs-up"></i><span> ' + String(rows) + '</span>';
            button.dataset.active = "0";
        }
        button.dataset.rows = rows;
    },

    // 싫어요 갱신
    setDislike: function (cid, active) {
        let button = document.getElementById("comment_" + cid).getElementsByClassName("btn-comment-dislike")[0];
        let rows = Number(button.dataset.rows);
        if (active) {
            rows = (rows + 1);
            button.innerHTML = '<i class="fas fa-thumbs-down"></i><span> ' + String(rows) + '</span>';
            button.dataset.active = "1";
        } else {
            rows = (rows > 0 ? rows - 1 : rows);
            button.innerHTML = '<i class="far fa-thumbs-down"></i><span> ' + String(rows) + '</span>';
            button.dataset.active = "0";
        }
        button.dataset.rows = rows;
    }
};

// 댓글 입력하면 창 크기 조절
$(document).on("keyup input", "textarea[data-autoresize]", function() {
    Comment.resizeTextarea(this);
});

// 댓글 글자수 확인
$(document).on('keydown keyup', "textarea.comment-content", function (e) {
    Comment.checkByte(this);
});

// 댓글 등록
$(document).on("click", "button.btn-comment-submit", function () {
    Comment.submit(this);
});

// 댓글 답글
$(document).on("click", "button.btn-comment-reply", function() {
    Comment.write(this, "reply");
});

// 댓글 수정
$(document).on("click", "button.btn-comment-edit", function () {
    Comment.write(this, "edit");
});

// 댓글 취소
$(document).on("click", "button.btn-comment-cancel", function () {
    Comment.cancel(this);
});

// 댓글 삭제
$(document).on("click", "button.btn-comment-delete", function () {
    Comment.delete(this);
});

// 댓글 신고
$(document).on("click", "button.btn-comment-blame", function() {
    Comment.blame(this);
});

// 댓글 추천하기
$(document).on("click", "button.btn-comment-like", function () {
    Comment.like(this);
});

// 댓글 비추천하기
$(document).on("click", "button.btn-comment-dislike", function () {
    Comment.dislike(this);
});

// 댓글 페이징 처리
$(document).on("click", "#commentList > nav > ul > li > a", function () {
    let page = Number(params('page', this.href));
    return Comment.list(page);
});

// 댓글 정렬
$(document).on("change", "select#commentSort", function () {
    Comment.list(null, null, null, this.value);
});

// 댓글 신고 모달 열리면 초기화
$(document).on("show.bs.modal", "#commentBlameModal", function(e) {
    let form = e.currentTarget.getElementsByTagName("form")[0];
    form.elements["type"].selectedIndex = 0;
    form.elements["reason"].value = "";

    if(!IS_USER) {
        return false;
    }
});
