/*
This module have to be independant of any external package
it is shared between back and front and is usefull
to apply common check in front before sending it in back
can be include in project with
  <script src="https://apiback.maildigit.fr/js/checkdata.js"></script>
or with const checkdata = require('../public/js/checkdata.js')

*/

// --##

const checkdata = {};
// each checkdata.test. return true or false
checkdata.test = {};

checkdata.test.emailadress = ( ctx, email ) => {
	const regExp = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
	return regExp.test( email );
};
/*
 * @emaillist = "email1,email2, email3"
 * it check if each eamil separate by , are correct
 */
checkdata.test.emailadresslist = ( ctx, emaillist ) => {
	//logger.info(emaillist.split(','))
	if( emaillist.length > 0 ) {
		const emails = emaillist.split( ',' );
		for( var i in emails ) {
			//logger.info(emails[i])
			if( !checkdata.test.emailadress( "", emails[ i ].trim() ) ) {
				return false
			}
		}
	};
	return true;
};

checkdata.test.password = ( ctx, pwd ) => {
	const regExp = new RegExp(
		/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&.])[A-Za-z\d$@$!%*?&.{}:|\s]{8,}/
	);
	return regExp.test( pwd );
};
checkdata.test.required = ( ctx, val ) =>
	( val != null && val != 'undefined' && val.length > 0 ) || ( !!val && val.constructor === Array && val.length > 0 ) || ( !!val && val.constructor === Object && Object.keys( val )
		.length > 0 );

checkdata.test.isNumber = ( ctx, n ) => typeof n === 'number';
checkdata.test.isInt = ( ctx, n ) => n != '' && !isNaN( n ) && Math.round( n ) == n;
checkdata.test.isFloat = ( ctx, n ) => n != '' && !isNaN( n ) && Math.round( n ) != n;
checkdata.test.unique = ( ctx, val ) => {
	if( ctx.list[ ctx.currentfield ] ) {
		return !ctx.list[ ctx.currentfield ].includes( val );
	} else {
		logger.info( 'ERR no list for field:' + ctx.currentfield );
		return false;
	}
};
checkdata.test.isDateDay = ( ctx, dateDay ) => true;
/* checkdata.test.filterInvalidInArray = (array, validate) =>
  array ? array.filter(el => !validate(el)) : true;
// return true when every elements is valid
*/

checkdata.test.postalCode = ( ctx, postalCode ) => {
	if( postalCode.length == 0 ) return true;
	const regExp = new RegExp( /(^\d{5}$)|(^\d{5}-\d{4}$)/ );
	return regExp.test( postalCode );
};
/**
 * PHONE
 */
checkdata.test.phoneNumber = ( ctx, phoneNumber ) => {
	if( phoneNumber.length == 0 ) return true;
	phoneNumber = phoneNumber.trim()
		.replace( /[- .]/g, '' )
	//french number
	const regExpfr = new RegExp( /^0[1-9][0-9]{9}$/ );
	const regExpInternational = new RegExp( /^\+*(\d{3})*[0-9,\-]{8,}/ );
	return regExpfr.test( phoneNumber ) || regExpInternational.test( phoneNumber );
};
/*
 * @phonelist = "phone1,phone2,phone3"
 * it check if each phone separate by , are correct
 */
checkdata.test.phoneNumberlist = ( ctx, phonelist ) => {
	//logger.info(emaillist.split(','))
	if( phonelist.length > 0 ) {
		const phones = phonelist.split( ',' );
		for( var i in phones ) {
			//logger.info(emails[i])
			if( !checkdata.test.phoneNumber( "", phones[ i ].trim() ) ) {
				return false
			}
		}
	};
	return true;
};

// checkdata.normalize take a correct data then reformat it to harmonise it
checkdata.normalize = {};
checkdata.normalize.phoneNumber = ( ctx, phone ) => {
	phone = phone.trim()
		.replace( /[- .]/g, '' );
	if( checkdata.test.phoneNumber( '', phone ) && phone.length == 10 && phone[ 0 ] == "0" ) {
		phone = '+33 ' + phone.substring( 1 );
	}
	return phone;
}
checkdata.normalize.upperCase = ( ctx, txt ) => txt.toUpperCase();
checkdata.normalize.lowerCase = ( ctx, txt ) => txt.toLowerCase();
// fixe 10 position et complete par des 0 devant
checkdata.normalize.zfill10 = ( ctx, num ) => {
	let s = num + '';
	while( s.length < 10 ) s = '0' + s;
	return s;
};
/*let tt = "+33 1   02.03 04 05";
logger.info(checkdata.test.phoneNumber('', tt))
logger.info(checkdata.normalize.phoneNumber('', tt))
*/
checkdata.evaluate = ( contexte, referential, data ) => {
	/*
	* contexte object {} with full info for evaluation
	* file referential path to get object to apply
	* data related to object
	- return {validefor =[keyword of error] if empty no error,
	          clean data eventually reformated
	           updateDatabase}
	 */
	logger.info( 'contexte', contexte );
	logger.info( 'referentiel', referential );
	logger.info( 'data', data );
	const invalidefor = [];
	const objectdef = {};
	const listfield = referential.map( ch => {
		objectdef[ ch.idfield ] = ch;
		return ch.idfield;
	} );

	Object.keys( data )
		.forEach( field => {
			if( !listfield.includes( field ) ) {
				// some data can be inside an object with no control at all
				// they are used for process only
				// i leave it in case it will become a non sens
				// invalidefor.push('ERRFIELD unknown of referentials ' + field);
			} else {
				if( objectdef[ field ].check ) {
					// check data with rule list in check
					objectdef[ field ].check.forEach( ctrl => {
						logger.info( 'ctrl', ctrl );
						contexte.currentfield = field;
						if( !checkdata.test[ ctrl ] ) {
							invalidefor.push( 'ERR check function does not exist :' + ctrl + '___' + field )
						} else {
							if( !checkdata.test[ ctrl ]( contexte, data[ field ] ) )
								invalidefor.push( 'ERR' + ctrl + '___' + field );
						}
					} );
				}

				if( objectdef[ field ].nouserupdate ) {
					// check if user can modify this information
					logger.info(
						'evaluation :' + field + ' -- ' + objectdef[ field ].nouserupdate,
						eval( objectdef[ field ].nouserupdate )
					);
					const evalright = eval( objectdef[ field ].nouserupdate );
					objectdef[ field ].nouserupdate = evalright;
				}
			}
		} );
	logger.info( {
		invalidefor,
		data
	} );
	return {
		invalidefor,
		data
	};
};

if( typeof module !== 'undefined' ) module.exports = checkdata;
