/*-------------------------------------------------------------------+
 * 1. 파일명: valid.biz.js
 * 2. 설  명: 업무로직과 관련한 유효성 점검 함수를 정의한다.
 * 3. 의존성: util.js, string.js
 * 4. 작성일: 2006.10.11.
 -------------------------------------------------------------------*/


/**
 * E 메일 주소 형식이 맞는지 검사하여 맞으면 true,
 * 형식에 맞지 않으면 false를 돌려 준다.
 */
function checkEmail(email) {
	if ( isEmpty(email) ) return true;

	var emailRegEx = /^[-\w]+@[-\w]+(\.[-\w]+){1,3}\s*$/g;

	return emailRegEx.test(email);
}


function checkEmailObj(emailObj) {
	return checkEmail(emailObj.value);
}


function validateEmail(email, fieldName) {
	if ( fieldName == undefined ) fieldName = "E메일";

	var valid = checkEmail(email);

	if ( ! valid ) {
		showMessage(fieldName + " 항목의 값이 E 메일의 형식에 맞지 않습니다.");

	}

	return valid;
}


function validateEmailObj(emailObj) {
	var valid = validateEmail(emailObj.value);

	if ( ! valid ) {
		emailObj.focus();
		emailObj.value = emailObj.value;
	}

	return valid;
}



/* 전화번호용 지역번호 목록 */
var tpLocalNoList = [
	"02" ,
	"031", "032", "033",
	"041", "042", "043",
	"051", "052", "053", "054", "055",
	"061", "062", "063", "064"
];


/**
 * Text형 입력 폼의 값이 올바른 전화번호(핸드폰 번호가 아닌)인지 확인하여
 * 올바르면 true를, 그렇지 않으면 적절한 메세지를 뿌려주고 false를 돌려 준다.
 * 전화번호의 각 요소는 대쉬(-)로 구별된 것으로 가정한다.
 *
 * @date 2004-02-02
 * @param obj  전화번호를 입력 받는 Text형 입력폼
 */
function checkTelNoObj(obj) {
	return checkTelNo(obj.value);
}


/**
 * 주어진 값이 올바른 전화번호(핸드폰 번호가 아닌)인지 확인하여
 * 올바르면 0를, 그렇지 않으면 적절한 음수를 돌려 준다.
 * 전화번호의 각 요소는 구별자(-)가 없는 것으로 가정한다.
 *
 * 오류시 돌려주는 음수의 의미는 다음과 같다.
 * <ul>
 * <li>-1 : 숫자와 대쉬(-) 이외의 문자 사용</li>
 * <li>-2 : 전화번호의 형식에 맞지 않음</li>
 * <li>-4 : 지역번호가 사용하지 않는 번호임</li>
 * <li>-8 : 국번호 자릿수가 3, 4자리가 아님</li>
 * <li>-16 : 맨 뒤 번호 자릿수가 4자리가 아님</li>
 * </ul>
 *
 * @date 2004-02-02
 * @param phoneNo  검사하려는 전화번호 값
 */
function checkTelNo(phoneNo) {
	// 빈값이면 검사하지 않는다.
	if ( trim(phoneNo) == "" ) return 0;

	phoneNo = removeChar(phoneNo, '-');

	if ( isNaN(phoneNo) ) return -1;


	/* 형식에 문자가 있는지 검사한다. */
	//var tpNoRegExp = /^(0[1-9]{1,2}-)?[\d]{3,4}-[\d]{4}$/;
	var tpNoRegExp = /^(02|0[3-6][1-5])?[1-9][\d]{6,7}$/;

	if ( ! tpNoRegExp.test(phoneNo) ) return -2;

	/* 각 요소를 자른다. */
	var localNo = ""; // 지역번호
	var areaNo  = ""; // 국번
	var restNo  = ""; // 기타 번호

	var hasLocalNo = ( phoneNo.length >= 9 && phoneNo.length <= 11 );

	/* 지역번호가 유무에 따라 처리. */
	if ( hasLocalNo ) {
		/* 지역번호가 있을 때. */

		/* 지역번호가 02인가? */
		if ( phoneNo.indexOf("02") == 0 ) {
			localNo = "02";
			areaNo  = ( phoneNo.length == 9
						? phoneNo.substr(2, 3) : phoneNo.substr(2, 4) );
			restNo  = phoneNo.substr(2 + areaNo.length);
		}
		else {
			localNo = phoneNo.substr(0, 3);
			areaNo  = ( phoneNo.length == 10
						? phoneNo.substr(3, 3) : phoneNo.substr(3, 4) );
			restNo  = phoneNo.substr(3 + areaNo.length);
		}
	}
	else {
		/* 지역번호가 없을 때. */
		areaNo  = ( phoneNo.length == 7
					? phoneNo.substr(0, 3) : phoneNo.substr(0, 4) );
		restNo  = phoneNo.substr(areaNo.length);
	}

	/* 지역 번호가 있을 때만 처리한다. */
	if ( hasLocalNo ) {
		/* 유효한 지역번호가 아니면 오류이다. */
		var isExistsLocalNo = existsInArray(tpLocalNoList, localNo);

		if ( ! isExistsLocalNo ) {
			return -4;
		}
	}

	// 국번호가 3자리에서 4자리인지 검사한다.
	if ( areaNo.length != 3 && areaNo.length != 4 ) {
		return -8;
	}

	// 나머지 번호를 검사한다.
	if ( restNo.length != 4 ) {
		return -16;
	}

	return 0;
}


/**
 * 주어진 값이 올바른 전화번호(핸드폰 번호가 아닌)인지 확인하여
 * 올바르면 0를, 그렇지 않으면 적절한 메세지를 뿌려주고 false를 돌려 준다.
 * 전화번호의 각 요소는 대쉬(-)로 구별된 것으로 가정한다.
 *
 * @date 2004-02-02
 * @param phoneNo  검사하려는 전화번호 값
 */
function validateTelNoObj(obj, fieldName) {
	var validResult = validateTelNo(obj.value, fieldName);

	if ( validResult < 0 ) {
		obj.focus();
	}

	return validResult;
}

/**
 * 주어진 값이 올바른 전화번호(핸드폰 번호가 아닌)인지 확인하여
 * 올바르면 0를, 그렇지 않으면 적절한 메세지를 뿌려주고 false를 돌려 준다.
 * 전화번호의 각 요소는 대쉬(-)로 구별된 것으로 가정한다.
 *
 * @date 2004-02-02
 * @param phoneNo  검사하려는 전화번호 값
 */
function validateTelNo(phoneNo, fieldName) {
	var validResult = checkTelNo(phoneNo);

	/* fieldName이 정의되어 있지 않다면 "전화번호"로 한다. */
	if ( fieldName == undefined ) fieldName = "전화번호";

	var msg = "";

	switch ( validResult ) {
		case -1 :
			msg = fieldName + "은(는) 숫자만 이용해서 입력해야 합니다.";
			break;

		case -2 :
			msg = fieldName + "의 형식에 맞지 않습니다.\n\n"
					+ "[지역번호][국번3,4자리][번호4자리]\n"
					+ "혹은 [국번3,4자리][번호4자리]";
			break;

		case -4 :
			msg = "지역번호가 현재 사용하지 않는 번호입니다.";
			break;

		case -8 :
			msg = "국번호는 3자리나 4자리이어야 합니다.";
			break;

		case -16 :
			msg = "맨 뒤 번호는 4자리를 입력해야 합니다.";
			break;
	}


	if ( validResult < 0 ) {
		alert(msg);
	}

	return validResult;
}


/**
 * 전화(혹은 팩스)번호의 값을 확인하여 유효한 경우이면 형식화한다.
 */
function formatTelNoObjIfValid(obj, fieldName) {
	if ( validateTelNo(obj.value, fieldName) == 0 ) {
		/* 유효한 값이면 형식화한다. */
		formatTelNoObj(obj);
	}
	else {
		/* 유효하지 않은 값이면 잡아 둔다. */
		obj.focus();
	}
}






/* 핸드폰용 지역번호 목록 */
var hpLocalNoList = [
	"010", "011", "016", "017", "018", "019"
];

/**
 * Text형 입력 폼의 값이 올바른 핸드폰(핸드폰 번호가 아닌)인지 확인하여
 * 올바르면 true를, 그렇지 않으면 적절한 메세지를 뿌려주고 false를 돌려 준다.
 * 핸드폰 번호의 각 요소는 대쉬(-)로 구별된 것으로 가정한다.
 *
 * @date 2004-02-02
 * @param obj  핸드폰 번호를 입력 받는 Text형 입력폼
 */
function checkHpNoObj(obj) {
	return checkHpNo(obj.value);
}


/**
 * 주어진 값이 올바른 핸드폰 번호(일반 전화번호가 아닌)인지 확인하여
 * 올바르면 true를, 그렇지 않으면 적절한 메세지를 뿌려주고 false를 돌려 준다.
 * 핸드폰 번호의 각 요소는 대쉬(-)로 구별된 것으로 가정한다.
 *
 * @date 2004-02-02
 * @param phoneNo  검사하려는 핸드폰 번호값
 */
function checkHpNo(phoneNo) {
	// 빈값이면 검사하지 않는다.
	if ( trim(phoneNo) == "" ) return 0;

	phoneNo = removeChar(phoneNo, '-');

	if ( isNaN(phoneNo) ) {
		return -1;
	}

	/* 형식에 문자가 있는지 검사한다. */
	//var hpNoRegExp = /^01[016789]-[\d]{3,4}-[\d]{4}$/;
	var hpNoRegExp = /^01[016789][\d]{7,8}$/;

	if ( ! hpNoRegExp.test(phoneNo) ) return -2;

	// 각 요소를 자른다.
	var localNo = phoneNo.substr(0, 3);; // 지역번호
	var areaNo  = ( phoneNo.length == 10
					? phoneNo.substr(3, 3) : phoneNo.substr(3, 4) ); // 국번
	var restNo  = phoneNo.substr(3 + areaNo.length); // 기타 번호

	// 유효한 지역번호가 아니면 오류이다.
	var isExistsLocalNo = existsInArray(hpLocalNoList, localNo);

	if ( ! isExistsLocalNo ) {
		return -4;
	}

	// 국번호가 3자리에서 4자리인지 검사한다.
	if ( areaNo.length != 3 && areaNo.length != 4 ) {
		return -8;
	}

	// 나머지 번호를 검사한다.
	if ( restNo.length != 4 ) {
		return -16;
	}

	return 0;
}


/**
 * 주어진 값이 올바른 전화번호(핸드폰 번호가 아닌)인지 확인하여
 * 올바르면 0를, 그렇지 않으면 적절한 메세지를 뿌려주고 false를 돌려 준다.
 * 전화번호의 각 요소는 대쉬(-)로 구별된 것으로 가정한다.
 *
 * @date 2004-02-02
 * @param phoneNo  검사하려는 전화번호 값
 */
function validateHpNoObj(obj, fieldName) {
	var validResult = validateHpNo(obj.value, fieldName);

	if ( validResult < 0 ) {
		obj.focus();
	}

	return validResult;
}

/**
 * 주어진 값이 올바른 전화번호(핸드폰 번호가 아닌)인지 확인하여
 * 올바르면 0를, 그렇지 않으면 적절한 메세지를 뿌려주고 false를 돌려 준다.
 * 전화번호의 각 요소는 대쉬(-)로 구별된 것으로 가정한다.
 *
 * @date 2004-02-02
 * @param phoneNo  검사하려는 전화번호 값
 */
function validateHpNo(phoneNo, fieldName) {
	var validResult = checkHpNo(phoneNo);

	/* fieldName이 정의되어 있지 않다면 "핸드폰 번호"로 한다. */
	if ( fieldName == undefined ) fieldName = "핸드폰 번호";

	var msg = "";

	switch ( validResult ) {
		case -1 :
			msg = fieldName + "은(는) 숫자만 이용해서 입력해야 합니다.";
			break;

		case -2 :
			msg = fieldName + "의 형식([지역번호 3자리][국번3,4자리][번호4자리])에 "
					+ " 맞지 않습니다.";
			break;

		case -4 :
			msg = "지역번호가 현재 사용하지 않는 번호입니다.";
			break;

		case -8 :
			msg = "국번호는 3자리나 4자리이어야 합니다.";
			break;

		case -16 :
			msg = "맨 뒤 번호는 4자리를 입력해야 합니다.";
			break;
	}


	if ( validResult < 0 ) {
		alert(msg);
	}

	return validResult;
}


/**
 * 핸드폰 번호의 값을 확인하여 유효한 경우이면 형식화한다.
 */
function formatHpNoObjIfValid(obj, fieldName) {
	if ( validateHpNo(obj.value, fieldName) == 0 ) {
		/* 유효한 값이면 형식화한다. */
		formatHpNoObj(obj);
	}
	else {
		/* 유효하지 않은 값이면 잡아 둔다. */
		obj.focus();
	}
}



function validateContactNoObj(obj, fieldName) {
	var result = validateContactNo(obj.value, fieldName);

	if ( result < 0 ) obj.focus();

	return result;
}


/**
 * 연락처의 번호가 유효한지 검사한다.
 * 연락처는 전화번호, 팩스번호, 핸드폰 번호를 모두 통칭하여 말한다.
 *
 * @param contactNo 유효성을 검증할 연락처 번호.
 * @param fieldName 유효성을 검증할 항목명. 없으면 "연락처"를 사용한다.
 */
function validateContactNo(contactNo, fieldName) {
	if ( contactNo == "" ) return 0;

	/* fieldName이 정의되지 않았다면 "연락처"를 사용한다. */
	if ( fieldName == undefined ) fieldName = "연락처";

	/* 전화/팩스 번호인지, 핸드폰 번호인지를 판단한다.
	   -1 : 알수 없음.
	   -2 : 지역번호 정보 없음.
	    1 : 전화/팩스번호.
	    2 : 핸드폰 번호. */
	var whichTypeNo = findWhichTypeNo(contactNo);

	var result = -1;
	if ( whichTypeNo == -1 || whichTypeNo == -2 || whichTypeNo == 1 ) {
		/* 알수없음이거나 지역번호가 없음 일반전화 지역번호이면 전화번호로 검사. */
		result = validateTelNo(contactNo, fieldName);
	}
	else if ( whichTypeNo == 2 ) {
		/* 핸드폰 번호이면 핸드폰 번호로 검사 */
		result = validateHpNo(contactNo, fieldName);
	}

	return result;
}


/**
 * 연락처의 번호가 구체적으로 어떤 번호인지
 * 판단하여 돌려 준다.
 *
 *  -1 : 알수 없음.
 *  -2 : 지역번호 정보 없음.
 *   1 : 전화/팩스번호.
 *   2 : 핸드폰 번호.
 */
function findWhichTypeNo(contactNo) {
	var whichTypeNo = -1;

	/* 형식이 맞는지 검사하여 맞지 않으면 알수 없음. */
	var contactNoRegExp = /^(0[1-9]{1,2}-)?[\d]{3,4}-[\d]{4}$/;

	if ( ! contactNoRegExp.test(contactNo) ) return -1;

	var tempArr = contactNo.split("-");

	/* 길이가 2이면 지역번호 없음. */
	if ( tempArr.length == 2 ) return -2;

	/* 전화지역번호에 있나? */
	if ( existsInArray(tpLocalNoList, contactNo) ) {
		whichTypeNo = 1;
	}
	/* 핸드폰지역번호에 있나? */
	else if ( existsInArray(hpLocalNoList, contactNo) ) {
		whichTypeNo = 2;
	}

	return whichTypeNo;
}


/**
 * Text형 입력폼의 값이 유효한 주민등록번호 인지를
 * 점검하여 유효하면 true를 돌려주고 유효하지 않으면
 * 적절한 메세지를 보여준 다음 false를 돌려준다.
 * 파라미터인 obj2가 넘어오지 않으면 obj1에 주민등록번호
 * 전체가 담겨 있는 것으로 가정하며, obj2가 넘어오면
 * 앞 6자리는 obj1에 뒤 7자리는 obj2에 담겨 있는 것으로
 * 가정한다.
 *
 * @작성일  2004-02-05
 * @param  obj1  전체 주민등록번호 혹은 주민등록번호
 *               앞 6자리를 담고 있는 Text형 입력폼 객체
 * @param  obj2  주민등록번호 뒤 7자리를 담고 있는 Text형 입력폼 객체
 */
function checkSSNObj(obj1, obj2) {
	var valid = true;

	if ( obj2 == undefined ) {
		valid = checkSSN(obj1.value);
	}
	else {
		valid = checkSSN(obj1.value, obj2.value);
	}

	return valid;
}

/**
 * 주민등록번호 유효성 여부를 점검하여 유효하면 true를
 * 유효하지 않으면 적절한 메세지를 보여주고 false를 돌려준다.
 * 파라미터의 갯수에 따라 그 의미가 조금 달라진다.
 * ssn2가 정의되지 않았으면, 대쉬(-)의 여부에
 * 상관없이 ssn1에 전체 주민등록번호가 담겨있는 것으로
 * 가정하고, ssn2가 정의되어 있으면 ssn1에 앞 6자리
 * ssn2에 뒤 7자리로 넘어오는 것으로 가정한다.
 *
 * @작성일  2004-02-05
 * @param  ssn1  전체 주민등록번호 혹은 주민등록번호 앞 6자리
 * @param  ssn2  주민등록번호 뒤 7자리
 */
function checkSSN(ssn1, ssn2) {
	var ssn = "";
	if ( ssn2 == undefined ) {
		ssn = ssn1;
	}
	else {
		ssn = ssn1 + "-" + ssn2;
	}

	var fmt1 = /^\d{6}-[1234]\d{6}$/;
    var fmt2 = /^\d{6}[1234]\d{6}$/;

	if ( !(fmt1.test(ssn) || fmt2.test(ssn)) ){
		//showMessage("잘못된 주민등록번호입니다.");
		return false;
	}

	// 날짜 유효성 검사
	var birthYear = (ssn.charAt(7) <= "2") ? "19" : "20";
		birthYear += ssn.substr(0, 2);
	var birthMonth = ssn.substr(2, 2) - 1;
	var birthDate = ssn.substr(4, 2);
	var birth = new Date(birthYear, birthMonth, birthDate);

	if ( birth.getYear() % 100 != ssn.substr(0, 2)
			|| birth.getMonth() != birthMonth
			|| birth.getDate() != birthDate ) {
		//showMessage("잘못된 주민등록번호입니다.");
		return false;
	}

	// Check Sum 코드의 유효성 검사
	var buf = new Array(13);

	for (var i = 0; i < 13; i++) {
		buf[i] = parseInt(ssn.charAt(i));
	}

	var multipliers = [2,3,4,5,6,7,8,9,2,3,4,5];
	var sum = 0;
	for (var i = 0; i < 12; i++) {
		sum += (buf[i] *= multipliers[i]);
	}

	var cal = 11 - (sum % 11);
	if( cal > 10 ) cal = cal / 11;
	else cal;
	if ( cal != buf[12] ) {
		//showMessage("잘못된 주민등록번호입니다.");
		return false;
	}

	return true;
}



function validateSSNObj(elem, fieldName) {
	var valid = checkSSN(elem.value);

	/* fieldName이 정의되어 있지 않다면 "주민등록번호"로 한다. */
	if ( fieldName == undefined ) fieldName = "주민등록번호";

	if ( ! valid ) {
		if (elem.value != "") {
			showMessage(fieldName + " 항목의 값은 잘못된 주민등록번호입니다.");
			elem.focus();
			elem.value = elem.value;
		}

	}

	return valid;
}

//<!------------------------------------------------------------------------------
// [문자열의 주민등록번호 유효성체크]
// function SSN(data)
// param :  String data - 데이타열(999999-9999999 OR 9999999999999)
// return : int 0=주민등록번호/0<주민등록번호아님
//------------------------------------------------------------------------------->

function SSN(data){
	var birth;
	var chkData;
	var fmt1;
	var fmt2;
	var sum;

	fmt1 = /^\d{6}-[1234]\d{6}$/;
	fmt2 = /^\d{6}[1234]\d{6}$/;

	if ( !(fmt1.test(data) || fmt2.test(data)) ){
		return false;
	}

	if (fmt1.test(data)){
		birth = (data.charAt(7) <= "2") ? "19" : "20";
		birth += data.substr(0, 6);
		chkData = birth;
		chkData += data.substr(7, 7);
	}else{
		birth = (data.charAt(6) <= "2") ? "19" : "20";
		birth += data.substr(0, 6);
		chkData = birth;
		chkData += data.substr(6, 7);
	}

	// 날짜 유효성 검사
	if ( SSNDate(birth) < 0 ){
		return false;
	}

	// Check Sum 코드의 유효성 검사
	buf = new Array(13);
	for (i = 0; i < 13;  i++) buf[i] = parseInt(chkData.charAt(i+2));

	multipliers = [2,3,4,5,6,7,8,9,2,3,4,5];
	for (i = 0, sum = 0; i < 12; i++) sum = sum + (buf[i] * multipliers[i]);

	if (((11 - (sum % 11)) % 10) != buf[12]){
		return false;
	}

	return true;
}

function SSNDate(data){
	var chkYear;
	var chkMonth;
	var chkDate;
	var chkData;
	var fmt1;
	var fmt2;
	var fmt3;

	fmt1 = /^\d{4}.\d{2}.\d{2}$/;
	fmt2 = /^\d{4}-\d{2}-\d{2}$/;
	fmt3 = /^\d{8}$/;

	if ( !(fmt1.test(data) || fmt2.test(data) || fmt3.test(data)) ){
		return -1;
	}

	if ( fmt1.test(data) || fmt2.test(data) ){
		chkYear = data.substr(0, 4);
		chkMonth = data.substr(5, 2) - 1;
		chkDay = data.substr(8, 2);
	}else{
		chkYear = data.substr(0, 4);
		chkMonth = data.substr(4, 2) - 1;
		chkDay = data.substr(6, 2);
	}

	// 날짜 유효성 검사
	chkData = new Date(chkYear, chkMonth, chkDay);
	if( chkData.getYear() < 100 )
		chkYear = chkYear.substr(2,2);
	if ( chkData.getYear() != chkYear ||
			chkData.getMonth() != chkMonth ||
			chkData.getDate() != chkDay)
	{
		return -2;
	}
	return 1;
}
