$(function() {
    Comment.init();
    Comment.list();

    // 댓글입력 창 높이 자동조정
    $.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", modify: "update", reply: "reply"},
    mode: "", // write, modify, reply
    code: "",
    bid: 0,
    pid: 0,
    cid: 0,
    total: 0,
    page: 0,
    perPage: 0,
    minLength: 0,
    maxLength: 0,
    listForm: null,
    writeForm: null,
    saveHtml: null,
    saveBefore: null,
    useEditor: false,

    // 댓글 기본설정
    init: function()
    {
        this.listForm = document.getElementById(this.listID);

        // 댓글 목록
        if(this.listForm !== null) {
            this.code = document.getElementById("code").value;
            this.bid = document.getElementById("bid").value;
            this.pid = document.getElementById("pid").value;
            this.callback = (BASE_URL + "/board/" + String(this.code) + "/" + String(this.pid) + "/comment");
        }

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

        // 댓글 입력창
        if(IS_USER && this.writeForm !== null) {
            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; // 댓글 입력 창 저장
            this.reset(form);
        }
    },

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

        if (typeof form !== "undefined") {
            form.elements["mode"].value = "write";
            form.elements["cid"].value = "";
            form.elements["length"].value = "0";
            form.elements["content"].value = "";
            if (typeof form.elements["is_secret"] !== "undefined") {
                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;
            }
        }
    },

    // 댓글 영역 강조
    focusCommentBox: function(cid)
    {
        if (typeof cid != "undefined" && cid) {
            $('#comment_' + cid).effect('highlight', {
                'color': '#FFFFC6'
            }, 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 (!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 형식으로 뎃글목록 출력
            let total = this.children.total.value;
            let page = this.children.page.value;
            let perPage = this.children.per_page.value;

            if (total) { // 댓글 수 표시
                document.getElementById("txtCommentRows").innerText = total;
                document.getElementById("txtPostCommentCnt").innerText = total;
            }
            if (message) { // 알림이 있을 경우 alert
                alert(message);
            }

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

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

        $(e.form).validate({
            onkeyup: false,
            onclick: false,
            onfocusout: false,
            rules: {
                mode: {required: true, contains: ["write", "modify", "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: Comment.maxLength
                },
                is_secret: {number: true}
            },
            messages: {
                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 mode = form.elements["mode"].value;
                let content = form.elements["content"].value;
                let spamKeyword = Comment.filterSpamKeyword(content); // 금지 단어 검사
                if (spamKeyword) {
                    alert("내용에 금지어 ('" + spamKeyword + "')가 포함 되어있습니다.");
                    form.elements["content"].focus();
                    return false;
                }

                // 댓글 등록
                let formData = $(form).serializeArray();
                formData.push({name: "bid", value: Comment.bid});
                formData.push({name: "pid", value: Comment.pid});

                // 버튼 비활성화
                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,
                    data: formData,
                    dataType: 'json',
                    beforeSend: function (xhr) {
                        if (!loginCheck()) {
                            xhr.abort();
                        }
                        showLoading();
                    },
                    success: function (res) {
                        if (res.success) {
                            let page = (mode === "write" ? Math.ceil((Number(Comment.total) + 1) / Comment.perPage) : Comment.page);
                            Comment.list(page, res.commentID);
                        }else{
                            alert(res.message);
                        }
                        Comment.reset(form);
                    },
                    error: function (xhr, status, err) {
                        procErrorEvent(xhr, status, err);
                    },
                    complete: function() {
                        hideLoading();
                    }
                });
            }
        });

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

    // 수정, 답글
    write: function(e, mode)
    {
        if(!loginCheck()) {
            return false;
        }
        if(typeof e === "undefined") {
            return false;
        }
        if(typeof mode == "undefined" || mode == null || !mode) {
            return false;
        }
        if($.inArray(mode, ["write", "modify", "reply"]) < 0) {
            return false;
        }

        let listForm = e.form; // 댓글 영역
        let writeForm = null;
        let cid = (listForm.elements["cid"].value || 0);
        let mediaFormID = ("#fCommentWrite_" + cid);
        let $saveBefore = $(this.saveBefore); // 이전 답글
        let $target = $(mediaFormID); // 현재 답글

        // 답글
        if(mode === "reply") {
            if(this.cid === cid && this.saveBefore === mediaFormID && this.mode === mode) {
                $saveBefore.toggle(); // 기존 댓글 창 보기/숨김
            }else{
                $saveBefore.html("");
                $target.show();
                writeForm = $target.html(this.saveHtml).get(0).firstElementChild;
                writeForm.elements["mode"].value = mode;
                writeForm.elements["cid"].value = cid;
            }
        }

        // 수정
        if(mode === "modify") {
            $saveBefore.html("");
            $target.show();
            writeForm = $target.html(this.saveHtml).get(0).firstElementChild;
            writeForm.elements["content"].value = listForm.content.value; // 내용 대입
            if(typeof writeForm.elements["is_secret"] !== "undefined") {
                writeForm.elements["is_secret"].checked = Boolean(listForm.is_secret.value === '1'); // 비밀글 체크
            }
            writeForm.elements["mode"].value = mode;
            writeForm.elements["cid"].value = cid;

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

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

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

            // 글자 수 확인
            this.checkByte(writeForm.elements["content"]);
        }

        this.mode = mode;
        this.cid = cid;
        this.saveBefore = mediaFormID; // 현재 영역
    },

    // 댓글 삭제
    delete: function(e)
    {
        e.blur();
        if (confirm("정말 삭제 하시겠습니까?")) {
            let bid = e.form.bid.value;
            let pid = e.form.pid.value;
            let cid = e.form.cid.value;

            $.ajax({
                url: (this.callback + "/delete"),
                type: 'delete',
                cache: false,
                async: false,
                data: {bid: bid, pid: pid, cid: cid, _method: "delete"},
                dataType: 'json',
                beforeSend: function(xhr) {
                    if(!loginCheck()) {
                        xhr.abort();
                    }
                },
                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;
        }

        let bid = e.form.bid.value;
        let pid = e.form.pid.value;
        let cid = e.form.cid.value;

        // 신고 접수 유효성
        $("#fCommentBlame").validate({
            onkeyup: false,
            onclick: false,
            onfocusout: false,
            rules: {
                blame_type: {required: true, contains: ['1', '2', '3', '4', '5', '6', '7', '8', '9']},
                blame_reason: {required: true, normalizer: function (value) {return $.trim(value);}, maxlength: 1000}
            },
            messages: {
                blame_type: {required: "신고 유형을 선택해주세요.", contains: "잘못된 요청입니다."},
                blame_reason: {required: "신고 내용을 입력해주세요.", maxlength: "신고 내용은 {0}자까지 입력 가능합니다."}
            },
            showErrors: function (errorMap, errorList) {
                if (this.numberOfInvalids()) {
                    alert(errorList[0].message);
                    errorList[0].element.focus();
                }
            },
            submitHandler: function(form) {
                if (confirm("신고를 접수하시겠습니까?")) {
                    $.ajax({
                        url: (this.callback + "/blame"),
                        type: 'post',
                        cache: false,
                        async: false,
                        data: {bid: bid, pid: pid, cid: cid, type: form.blame_type.value, reason: form.blame_reason.value},
                        dataType: 'json',
                        beforeSend: function (xhr) {
                            if(!loginCheck()) {
                                xhr.abort();
                            }
                        },
                        success: function (res) {
                            form.blame_type.value = "";
                            form.blame_reason.value = "";
                            if (res.success) {
                                alert("감사합니다. 신고가 접수되었습니다. 이용 규칙을 위반한 것으로 확인되면 댓글이 삭제됩니다.");
                            }else{
                                alert(res.message || "처리 중 오류가 발생하였습니다. 관리자에게 문의하십시오.");
                            }
                            $('div.modal').modal('hide');
                        },
                        error: function (xhr, status, err) {
                            procErrorEvent(xhr, status, err);
                        }
                    });
                }
            }
        });
    },

    // 추천
    like: function (e) {
        let bid = e.form.bid.value;
        let pid = e.form.pid.value;
        let cid = e.form.cid.value;
        let type = e.value;
        let active = Number(e.dataset.active);

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

    // 비추천
    dislike: function (e) {
        let bid = e.form.bid.value;
        let pid = e.form.pid.value;
        let cid = e.form.cid.value;
        let type = e.value;
        let active = Number(e.dataset.active);

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

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

    /*
     * 댓글 에디터 옵션 변경
     * 1:1 게시판에서 댓글을 작성하면 실행
     */
    setInitEditor: function () {
        let tinyMCEExtendSetting = {
            min_height: 210,
            max_height: 310,
            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;
                });
            }
        };

        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-modify", function () {
    Comment.write(this, "modify");
});

// 댓글 취소
$(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["blame_type"].selectedIndex = 0;
    form.elements["blame_reason"].value = "";
});
