(function ($) {
    $.extend($.validator.messages, {
        required: "필수 항목입니다.",
        remote: "항목을 수정하세요.",
        email: "유효하지 않은 E-Mail주소입니다.",
        url: "유효하지 않은 URL입니다.",
        date: "올바른 날짜를 입력하세요.",
        dateISO: "올바른 날짜(ISO)를 입력하세요.",
        number: "유효한 숫자가 아닙니다.",
        digits: "숫자만 입력 가능합니다.",
        creditcard: "신용카드 번호가 바르지 않습니다.",
        equalTo: "같은 값을 다시 입력하세요.",
        extension: "올바른 확장자가 아닙니다.",
        maxlength: $.validator.format("{0}자를 넘을 수 없습니다. "),
        minlength: $.validator.format("{0}자 이상 입력하세요."),
        rangelength: $.validator.format("문자 길이가 {0} 에서 {1} 사이의 값을 입력하세요."),
        range: $.validator.format("{0} 에서 {1} 사이의 값을 입력하세요."),
        max: $.validator.format("{0} 이하의 값을 입력하세요."),
        min: $.validator.format("{0} 이상의 값을 입력하세요.")
    });

    $.validator.methods.number = function (value, element) {
        return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:[\s\.,]\d{3})+)(?:[\.,]\d+)?$/.test(value);
    }

    $.validator.methods.min = function (value, element, param) {
        let globalizedValue = value.replace(",", ".");
        return this.optional(element) || globalizedValue >= param;
    }

    $.validator.methods.max = function (value, element, param) {
        let globalizedValue = value.replace(",", ".");
        return this.optional(element) || globalizedValue <= param;
    }

    $.validator.methods.range = function (value, element, param) {
        let globalizedValue = value.replace(",", ".");
        return this.optional(element) || (globalizedValue >= param[0] && globalizedValue <= param[1]);
    }

    $.validator.addMethod('hangul', function (value, element) { // (자음, 모음만 있는 한글은 처리하지 않습니다.)
        return this.optional(element) || validHangul(value);
    }, '한글로 입력해주세요.');

    $.validator.addMethod('alpha_num_under', function (value, element) {
        return this.optional(element) || /(^[a-zA-Z0-9\_]+$)/.test(value);
    }, '영문, 숫자, _ 가 아닙니다.');

    $.validator.addMethod('alpha_dash', function (value, element) {
        return this.optional(element) || /(^[a-zA-Z0-9\_\-]+$)/.test(value);
    }, '영문, 숫자, _ , - 가 아닙니다.');

    $.validator.addMethod('valid_tinymce', function (value, element) {
        return validTinyEditor($(element).attr('name'), $(element).attr('id'), value, 'valid');
    }, '내용을 입력해주세요');

    $.validator.addMethod('required_tinymce', function (value, element) {
        return validTinyEditor($(element).attr('name'), $(element).attr('id'), value, 'required');
    }, '내용을 입력해주세요');

    $.validator.addMethod("greaterThan", function (value, element, params) {
        let target = $(params).val();
        let isValueNumeric = !isNaN(parseFloat(value)) && isFinite(value);
        let isTargetNumeric = !isNaN(parseFloat(target)) && isFinite(target);
        if (isValueNumeric && isTargetNumeric) {
            return Number(value) > Number(target);
        }

        if (!/Invalid|NaN/.test(new Date(value))) {
            return new Date(value) > new Date(target);
        }
    }, '날짜를 확인해주세요.');

    $.validator.addMethod('is_phone', function (value) {
        return isValidPhone(value); // 성공예시 : 010-XXXX-XXXX 또는 010XXXXXXXX
    }, '연락처 형식이 잘못되었습니다.');

    $.validator.addMethod('is_ip', function (value) {
        return isValidIP(value); // 성공예시 : 192.168.56.101
    }, 'IP 형식이 잘못되었습니다.');

    $.validator.addMethod('is_comma_digits', function (value) {  // 콤마(`,`)가 추가된 숫자형태 인가?
        return $.isNumeric(value.replace(',', ''));
    }, '숫자를 입력해주세요.');

    $.validator.addMethod("greaterThan", function (value, element, params) {
        if (!/Invalid|NaN/.test(new Date(value))) {
            return new Date(value) >= new Date($(params).val());
        }
        if(this.optional(element)) {
            return true;
        }
        return isNaN(value) && isNaN($(params).val()) || (Number(value) > Number($(params).val()));
    }, '기간 입력 날짜가 잘못되었습니다.');

    $.validator.addMethod("contains", function (value, element, param) { // [] 배열안에 문자가 포함되어 있는가?
        let contains = false;
        for (let i = 0; i < param.length; i++) {
            if (value.includes(param[i])) {
                contains = true;
            }
        }
        return this.optional(element) || contains;
    }, "");

    $.validator.addMethod('file_size', function (value, element, param) {
        return this.optional(element) || (element.files[0].size <= param * 1000000);
    }, '파일은 최대 `{0}MB`까지 첨부 가능합니다.');

    $.validator.addMethod('numeric', function (value, element, param) { // 숫자가 몇개 이상인지 확인
        let i = 0;
        let character = '';
        let count = 0;
        while (i <= value.length) {
            character = value.charAt(i); // 해당 index에 문자 반환
            if (!isNaN(character * 1)) {
                count++;
            }
            i++;
        }
    }, '소문자가 {0}개 이상 포함되어야 합니다.');

    $.validator.addMethod('uppercase', function (value, element, param) { // 대문자가 몇개 이상인지 확인
        let i = 0;
        let character = '';
        let count = 0;
        while (i <= value.length) {
            character = value.charAt(i); // 해당 index에 문자 반환
            if (character === character.toUpperCase()) {
                count++;
            }
            i++;
        }
    }, '대문자가 {0}개 이상 포함되어야 합니다.');

    $.validator.addMethod('lowercase', function (value, element, param) { // 소문자가 몇개 이상인지 확인
        let i = 0;
        let character = '';
        let count = 0;
        while (i <= value.length) {
            character = value.charAt(i); // 해당 index에 문자 반환
            if (character === character.toLowerCase()) {
                count++;
            }
            i++;
        }
    }, '소문자가 {0}개 이상 포함되어야 합니다.');

    // 이메일 유효성 확인
    $.validator.addMethod('is_email_able', function (value, element) {
        let ret = '';
        $.ajax({
            headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')},
            url: BASE_URL + '/api/isEmailAble',
            type: 'POST',
            dataType: 'JSON',
            async: false,
            cache: false,
            data: {email: value},
            success: function (res) {
                ret = res;
            }
        });
        return ret;
    }, '이 이메일은 사용하실 수 없습니다.');

    // 비밀번호 유효성 확인
    $.validator.addMethod('is_password_able', function (value, element) {
        let ret = '';
        $.ajax({
            headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')},
            url: BASE_URL + '/api/isPasswordAble',
            type: 'POST',
            dataType: 'JSON',
            async: false,
            cache: false,
            data: {password: value},
            success: function (res) {
                ret = res;
            }
        });
        return ret;
    }, '이 비밀번호는 사용하실 수 없습니다.');

    // 연락처 유효성 확인
    $.validator.addMethod('is_phone_able', function (value, element) {
        let ret = '';
        $.ajax({
            headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')},
            url: BASE_URL + '/api/isPhoneAble',
            type: 'POST',
            dataType: 'JSON',
            async: false,
            cache: false,
            data: {phone: value},
            success: function (res) {
                ret = res;
            }
        });
        return ret;
    }, '이 연락처는 사용하실 수 없습니다.');

    // 닉네임 유효성 확인
    $.validator.addMethod('is_nickname_able', function (value, element) {
        let ret = '';
        $.ajax({
            headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')},
            url: BASE_URL + '/api/isNicknameAble',
            type: 'POST',
            dataType: 'JSON',
            async: false,
            cache: false,
            data: {nickname: value},
            success: function (res) {
                ret = res;
            }
        });
        return ret;
    }, '이 닉네임은 사용하실 수 없습니다.');

}(jQuery));

function validHangul(fld) {
    let pattern = /([^가-힣\x20])/i;
    return (!pattern.test(fld) ? true : false);
}

function validTinyEditor(name, id, value, stype) {
    if (tinymce.editors.length > 0) {
        // let editorData = tinymce.activeEditor.getContent({format: 'raw'}); // tinymce 안에 데이터 조회
        let editorData = tinymce.EditorManager.get(id).getContent({format: 'raw'}); // tinymce 안에 데이터 조회

        // 아무 값이 없으면 영역을 비어둔다.
        if ($.inArray(editorData.toLowerCase().replace(/^\s*|\s*$/g, ''), ['&nbsp;', '<p>&nbsp;</p>', '<p><br/></p>', '<div><br/></div>', '<p></p>', '<br/>', '<p><br data-mce-bogus="1"/></p>', '<br data-mce-bogus="1"/>'], '') != -1) {
            tinymce.get(id).setContent('');
        }

        if (stype === "required") {
            if (!editorData || $.inArray(editorData.toLowerCase(), ['&nbsp;', '<p>&nbsp;</p>', '<p><br/></p>', '<p></p>', '<br/>', '<p><br data-mce-bogus="1"></p>', '<br data-mce-bogus="1">']) != -1) {
                // tinymce.get(column).focus(); // tinymce 에디터 영역에 포커스 이동
                tinymce.EditorManager.get(id).focus(); // $("#"+column).tinymce().focus();
                return false;
            }
        }
    } else {
        if (stype === "required" && !value) {
            document.getElementById(id).focus();
            return false;
        }
    }
    return true;
}

// IP4 Address 검사
function isValidIP(value) {
    let format = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
    return (!value.match(format) ? false : true);
}

// 휴대폰 인가 확인
function isValidPhone(value) {
    let phoneExp = /^\d{3}-\d{3,4}-\d{4}$/;
    let telExp = /^\d{2,3}-\d{3,4}-\d{4}$/;

    if (!phoneExp.test(value)) {
        return false; // 휴대폰 번호가 아니라면
    } else if (!telExp.test(value)) {
        return false; // 일반 전화번호가 아니라면
    } else {
        return true;
    }
}

/*
 * 부동소수점 숫자인지 음수부호도 포함하여 검사
 */
function isDouble(x) {
    let reg = /^[-|+]?\d+\.?\d*$/;
    return reg.test(x);
}

/*
 * 부동소수점 숫자인지 검사
 * cf) 음수부호는 포함하지 않음
 */
function isDoublePlus(x) {
    let reg = /^\d+\.?\d*$/;
    return reg.test(x);
}

/*
 * 정수인지 음수부호도 포함하여 검사
 */
function isInteger(x) {
    let reg = /^[-|+]?\d+$/;
    return reg.test(x);
}

/*
 * 한글이 포함하는지 검사
 */
function isHangle(value) {
    let regExp = /[ㄱ-ㅎ|ㅏ-ㅣ|가-힣]/g;
    return (regExp.test(value) ? true : false);
}

/*
 * 숫자(0~9)와 문자(A(a)~Z(z))로만 이루어진 문자열인지 검사
 * cf) space가 true면 공백문자를 포함한다.
 */
function isAlphaNumeric(x, space) {
    let reg;
    if (space) {
        reg = /^[a-z A-Z0-9]+$/;
    } else {
        reg = /^[a-zA-Z0-9]+$/;
    }
    return reg.test(x);
}

/*
 * 문자(A(a)~Z(z))로만 이루어진 문자열인지 검사
 * cf) space가 true면 공백문자를 포함한다.
 */
function isAlphabetic(x, space) {
    let reg;
    if (space) {
        reg = /^[a-z A-Z]+$/;
    } else {
        reg = /^[a-zA-Z]+$/;
    }
    return reg.test(x);
}

/*
 *  email 형식의 문자열인지 검사
 */
function isEmail(str) {
    let regEmil = /[a-z0-9]{2,}@[a-z0-9-]{2,}\.[a-z0-9]{2,}/i
    return regEmil.test(str);
}

/*
 * 입력값이 NULL인지 체크
 */
function isNull(input) {
    return ((input.value == null && input.value == "") ? true : false);
}

/*
 * 입력값에 스페이스 이외의 의미있는 값이 있는지 체크
 * ex) if (isEmpty(form.keyword)) {
 *         alert("검색조건을 입력하세요.");
 *     }
 */
function isEmpty(input) {
    return ((input.value == null && input.value.replace(/ /gi, "") == "") ? true : false);
}

/*
 * 입력값에 특정 문자(chars)가 있는지 체크
 * 특정 문자를 허용하지 않으려 할 때 사용
 * ex) if (containsChars(form.name,"!,*&^%$#@~;")) {
 *         alert("이름 필드에는 특수 문자를 사용할 수 없습니다.");
 *     }
 */
function containsChars(input, chars) {
    for (let inx = 0; inx < input.value.length; inx++) {
        if (chars.indexOf(input.value.charAt(inx)) != -1) {
            return true;
        }
    }
    return false;
}

/*
 * 입력값이 특정 문자(chars)만으로 되어있는지 체크
 * 특정 문자만 허용하려 할 때 사용
 * ex) if (!containsCharsOnly(form.blood,"ABO")) {
 *         alert("혈액형 필드에는 A,B,O 문자만 사용할 수 있습니다.");
 *     }
 */
function containsCharsOnly(input, chars) {
    for (let inx = 0; inx < input.value.length; inx++) {
        if (chars.indexOf(input.value.charAt(inx)) == -1) {
            return false;
        }
    }
    return true;
}

/*
 * 입력값이 알파벳인지 체크
 * 아래 isAlphabet() 부터 isNumComma()까지의 메소드가
 * 자주 쓰이는 경우에는 let chars 변수를
 * global 변수로 선언하고 사용하도록 한다.
 * ex) let uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 *     let lowercase = "abcdefghijklmnopqrstuvwxyz";
 *     let number    = "0123456789";
 *     function isAlphaNum(input) {
 *         let chars = uppercase + lowercase + number;
 *         return containsCharsOnly(input,chars);
 *     }
 */
function isAlphabet(input) {
    let chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    return containsCharsOnly(input, chars);
}

/*
 * 입력값이 알파벳 대문자인지 체크
 */
function isUpperCase(input) {
    let chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    return containsCharsOnly(input, chars);
}

/*
 * 입력값이 알파벳 소문자인지 체크
 */
function isLowerCase(input) {
    let chars = "abcdefghijklmnopqrstuvwxyz";
    return containsCharsOnly(input, chars);
}

/*
 * 입력값에 숫자만 있는지 체크
 */
function isNumber(input) {
    let chars = "0123456789";
    return containsCharsOnly(input, chars);
}

/*
 * 입력값이 알파벳,숫자로 되어있는지 체크
 */
function isAlphaNum(input) {
    let chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    return containsCharsOnly(input, chars);
}

/*
 * 입력값이 숫자,대시(-)로 되어있는지 체크
 */
function isNumDash(input) {
    let chars = "-0123456789";
    return containsCharsOnly(input, chars);
}

/*
 * 입력값이 숫자,콤마(,)로 되어있는지 체크
 */
function isNumComma(input) {
    let chars = ",0123456789";
    return containsCharsOnly(input, chars);
}

/*
 * 입력값이 사용자가 정의한 포맷 형식인지 체크
 * 자세한 format 형식은 자바스크립트의 `regular expression`을 참조
 */
function isValidFormat(input, format) {
    return ((input.value.search(format) != -1) ? true : false);
}

/*
 * 입력값이 이메일 형식인지 체크
 * ex) if (!isValidEmail(form.email)) {
 *         alert("올바른 이메일 주소가 아닙니다.");
 *     }
 */
function isValidEmail(input) {
    let format = /^((\w[\-\.])+)@((\w[\-\.])+)\.([A-Za-z]+)$/;
    return isValidFormat(input, format);
}

// URL 형식이 맞는지 확인
function isValidURL(data) {
    return /^(((http(s?))\:\/\/)?)([0-9a-zA-Z\-]+\.)+[a-zA-Z]{2,6}(\:[0-9]+)?(\/\S*)?/.test(data);
}

/*
 * 입력값이 전화번호 형식(숫자-숫자-숫자)인지 체크
 */
// function isValidPhone(input) {
//     let format = /^(\d+)-(\d+)-(\d+)$/;
//     return isValidFormat(input, format);
// }
