/**
 * dateFeedRtn.js
 * 日付送り戻し機能を追加します。
 *
 * 第一引数は、分類を指定します。
 *  ・Y   ：年の形を指定します。
 *  ・YM  ：年月の形を指定します。
 *  ・YMD ：年月日の形を指定します。
 * 第二引数は、識別名を指定します。
 * 第三引数は、初期値を指定します。
 * 第四引数は、日付についての加減算処理を行うためのコマンドを指定します。
 *  ・SYXX ：年の最初の日付を指定の分だけ進めます。(SY-1なら先年の1月1日、SY1なら翌年の1月1日)
 *  ・SDXX ：月の最初の日付を指定の分だけ進めます。(SD-1なら先月の1日、SD1なら翌月の1日)
 *  ・SWXX ：週初め(月曜日)を指定の分だけ進めます。(SW-1なら先週の月曜日、SW1なら翌週の月曜日)
 *  ・EYXX ：年の最後の日付を指定の分だけ進めます。(EY-1なら先年の年末、EY1なら翌年の年末)
 *  ・EDXX ：月の最後の日付を指定の分だけ進めます。(ED-1なら先月の月末、ED1なら翌月の月末)
 *  ・EWXX ：週末(日曜日)を指定の分だけ進めます。(EW-1なら先週の日曜日、EW1なら翌週の日曜日)
 *  ・YXX  ：年を指定の分だけ進めます。(Y-1なら1年前、Y1なら1年後)
 *  ・MXX  ：月を指定の分だけ進めます。(M-1なら1月前、M1なら1月後)
 *  ・DXX  ：日を指定の分だけ進めます。(D-1なら1日前、D1なら1日後)
 *  ※ 数字がゼロのコマンドは初期化します。
 *  ※ 数字がないコマンドはサーバー上のシステム日付をセットします。
 * 第五引数は、検索ボタンを押すか押さないか[true/false]を指定します。 (初期値:false)
 *
 * @og.rev 8.0.2.0 (2021/11/30) 新規作成
 *
 */
function dateFeedRtn(_cat ,_tgtid, _dfVal, _prm, _isSubm) {
	var _dtStr, _val;
	var _cnt = parseInt(_prm.match(/[+-]?\d+/g));

	// システム日付をセットします。(例：D)
	if( !$.isNumeric(_cnt)) {
		_dtStr = _getSysDate(_cat);
	// 初期値をセットします。(例：D0)
	} else if( _cnt == 0 ) {
		_dtStr = ( _dfVal ) ? _dfVal : _getSysDate(_cat);
	// 日付加減算を行います。(例：D-1 or D+1)
	} else {
		_val = $("#"+_tgtid).val().replace(/\//g,"");
		if( _val ) {
			// 年月日の形で、入力値が年月の場合等は処理を行いません。
			if( (_cat == 'Y'   && _val.length == 4)
			 || (_cat == 'YM'  && _val.length == 6)
			 || (_cat == 'YMD' && _val.length == 8) )
			{
				if( _isDate(_cat, _val) ) {
					_dtStr = _addDate(_cat, _val, _prm, _cnt);
				}
			}
		}
	}

	// 識別名に値をセットします。
	if( _dtStr ) {
		$("#"+_tgtid).val(_dtStr).change();
		if( _isSubm == 'true' ) {
			// 検索ボタンを押します。
			$("#queryButtonSubmit").click();
		}
	}
}

// 日付加減算
var _addDate = (function(_cat, _val, _prm, _cnt) {
	var _newDt, _newCnt, _fmtVal;

	// 文字列を日付オブジェクトに変換します。(IE対応)
	switch (_cat) {
		case 'Y'  : _fmtVal = _val; break;
		case 'YM' : _fmtVal = _val.replace(/(\d{4})(\d{2})/, "$1/$2") + '/01'; break;
		default   : _fmtVal = _val.replace(/(\d{4})(\d{2})(\d{2})/, "$1/$2/$3");
	}
	var _dt = new Date(_fmtVal);
	var _y = _dt.getFullYear();
	var _m = _dt.getMonth();
	var _d = _dt.getDate();

	// SYXX ：年の最初の日付を指定の分だけ進めます。(SY-1なら先年の1月1日、SY1なら翌年の1月1日)
	if( !_prm.indexOf( 'SY' ) ) {
		_newCnt = _reorgCnt(_prm, _dt, _cnt, _m);
		_dt.setFullYear(_y + _newCnt);
		_dt = new Date(_dt.getFullYear() , 0, 1);
	// SDXX ：月の最初の日付を指定の分だけ進めます。(SD-1なら先月の1日、SD1なら翌月の1日)
	} else if( !_prm.indexOf( 'SD' ) ) {
		_newCnt = _reorgCnt(_prm, _dt, _cnt, _d-1);
		_dt.setMonth(_m + _newCnt);
		_dt = new Date(_dt.getFullYear(), _dt.getMonth(), 1);
	// SWXX ：週初め(月曜日)を指定の分だけ進めます。(SW-1なら先週の月曜日、SW1なら翌週の月曜日)
	} else if( !_prm.indexOf( 'SW' ) ) {
		// 開始日を月曜日(MONDAY=1)にセットします。
		// 指定日が日曜日の場合は、月曜日まで戻します。
		_newCnt = _reorgCnt(_prm, _dt, _cnt, 1);
		_dt.setDate(_d - _dt.getDay() + (_dt.getDay() == 0 ? -6 : 1) + (7 * _newCnt));
	// EYXX ：年の最後の日付を指定の分だけ進めます。(EY-1なら先年の年末、EY1なら翌年の年末)
	} else if( !_prm.indexOf( 'EY' ) ) {
		_newCnt = _reorgCnt(_prm, _dt, _cnt, 0);
		_dt.setFullYear(_y + _newCnt);
		_dt = new Date(_dt.getFullYear(), 12, 0);
	// EDXX ：月の最後の日付を指定の分だけ進めます。(ED-1なら先月の月末、ED1なら翌月の月末)
	} else if( !_prm.indexOf( 'ED' ) ) {
		// 2021/01/31 の翌月の最終日が 2021/03/31 となるのは、本来翌月になる 2021/02/28 までしかない為
		// 指定日の最後の日付を取得します。
		_newDt = new Date(_y, _m+1, 0);
		// 指定日の最初の日付にセットします。
		_dt = new Date(_y, _m, 1);
		_newCnt = _reorgCnt(_prm, _dt, _cnt, _newDt.getDate()-_d);
		_dt.setMonth(_m + _newCnt);
		_dt = new Date(_dt.getFullYear(), _dt.getMonth()+1, 0);
	// EWXX ：週末(日曜日)を指定の分だけ進めます。(EW-1なら先週の日曜日、EW1なら翌週の日曜日)
	} else if( !_prm.indexOf( 'EW' ) ) {
		// 終了日を日曜日(SUNDAY=0)がにセットします。
		_newCnt = _reorgCnt(_prm, _dt, _cnt, 0);
		_dt.setDate(_d - _dt.getDay() + (7 * _newCnt));
	// YXX ：年を指定の分だけ進めます。(Y-1なら1年前、Y1なら1年後)
	} else if( !_prm.indexOf( 'Y' ) ) {
		_dt.setFullYear(_y + _cnt);
	// MXX ：月を指定の分だけ進めます。(M-1なら1月前、M1なら1月後)
	} else if( !_prm.indexOf( 'M' ) ) {
		// 2021/01/31 の翌月が 2021/03/03 となるのは、31日で計算されて月が繰り上がる為
		_newCnt = ( _cnt > 0 ) ? 1 : -1;
		for (let i = 0; i < Math.abs(_cnt); i++) {
			if( i > 0 ) {
				var _y = _dt.getFullYear();
				var _m = _dt.getMonth();
				var _d = _dt.getDate();
			}
			// 翌月の最終日を取得します。
			if( _cnt > 0) {
				_mNew = _m+2;
				_dNew = new Date(_y, _mNew, 0).getDate();
			// 前月の最終日を取得します。
			} else {
				_mNew = _m;
				_dNew = new Date(_y, _mNew, 0).getDate();
			}
			// 当月の最後の日付の場合は、翌月／前月の最後の日付を取得します。
			if( _d > _dNew ) {
				_dt = new Date(_y, _mNew, 0);
			} else {
				_dt.setMonth(_m + _newCnt);
			}
		}
	// DXX ：日を指定の分だけ進めます。(D-1なら1日前、D1なら1日後)
	} else if( !_prm.indexOf( 'D' ) ) {
		_dt.setDate(_d + _cnt);
	}

	return _fmtDate(_cat, _dt, _val) ;
})

// システム日付取得
var _getSysDate = (function(_cat) {
	var _dt = new Date();
	return _fmtDate(_cat, _dt, null);
})

// 日付フォーマット(YYYYMMDD形式)
var _fmtDate = (function(_cat, _dt, _val) {
	var _dtStr;
	var _y = _dt.getFullYear();
	var _m = ("00" + (_dt.getMonth()+1)).slice(-2);
	var _d = ("00" + _dt.getDate()).slice(-2);

	// 日付オブジェクトを文字列に変換します。
	switch (_cat) {
		case 'Y'  : _dtStr = _y; break;
		case 'YM' : _dtStr = _y + _m; break;
		default   : _dtStr = _y + _m + _d;
	}
	return _isDate(_cat, _dtStr) ? _dtStr : _val;
})

// 日付の妥当性チェック
var _isDate = (function(_cat, _dtStr) {
	var _fDtStr;
	// 文字列を日付オブジェクトに変換します。(IE対応)
	switch (_cat) {
		case 'Y'  : _fDtStr = _dtStr + '/01/01'; break;
		case 'YM' : _fDtStr = _dtStr.replace(/(\d{4})(\d{2})/, "$1/$2") + '/01'; break;
		default   : _fDtStr = _dtStr.replace(/(\d{4})(\d{2})(\d{2})/, "$1/$2/$3");
	}

	var _dt = new Date(_fDtStr);
	// 日付の妥当性チェックを行います。
	if(	_dt.getFullYear() != parseInt(_fDtStr.split("/")[0])
		|| _dt.getMonth() != parseInt(_fDtStr.split("/")[1]) - 1
		|| _dt.getDate()  != parseInt(_fDtStr.split("/")[2])	)
	{
		return false;
	} else {
		return true;
	}
})

// 加減算数字の再編成
var _reorgCnt = (function(_prm, _dt, _cnt, _u) {
	var _newCnt;
	// 週
	if( ~_prm.indexOf( 'W' ) ) {
		if( _dt.getDay() != _u ) {
			if( Math.abs(_cnt) == 1 ){
				_newCnt = ( _cnt > 0 ) ? _cnt : _cnt +1;
			}
		}
	// 年／月
	} else {
		// 最初の日付
		if( !_prm.indexOf( 'S' ) ) {
			if( Math.abs(_cnt) == 1 ){
				_newCnt = ( _cnt > 0 ) ? _cnt : ( _u == 0 ) ? -1 : 0;
			}
		// 最後の日付
		} else {
			if( Math.abs(_cnt) == 1 ){
				_newCnt = ( _cnt > 0 ) ? ( _u == 0 ) ? _cnt : 0 : -1;
			}
		}
	}
	return ( _newCnt == null ) ? _cnt : _newCnt;
})
