package in.gov.digilocker.uidai.web.validator;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.xml.bind.DatatypeConverter;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import in.gov.digilocker.uidai.web.exceptions.LengthMismatchException;
import in.gov.digilocker.uidai.web.exceptions.ValueNotPassedException;

@Service
public class Validator {

	@Autowired HMacAlgorithm hmac;

	public String getCurrentDateTimeISOFormat() {
		String cTime = null;
		Date dt = new Date();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
		String currentTime = sdf.format(dt);
		cTime = currentTime;
		return cTime;
	}

	public String generateTransactionId(String uniqueReqId, String aadhaarNumber, String authType) throws NoSuchAlgorithmException {
		if ((uniqueReqId != null) && (!"".equals(uniqueReqId))) {
			return generateTransactionIdBasedOnAuthType(uniqueReqId, aadhaarNumber, authType);
		}
		return generateTransactionIdBasedOnAuthType(getUniqueTransactionId(aadhaarNumber), aadhaarNumber, authType);
	}

	private String generateTransactionIdBasedOnAuthType(String uniqueReqId, String aadhaarNumber, String authType) {
		if (("kyc".equalsIgnoreCase(authType)) && (!uniqueReqId.contains("UKC"))) {
			uniqueReqId = ("UKC:" + uniqueReqId).trim();
		}
		return uniqueReqId;
	}

	private static String getUniqueTransactionId(String aadhaarNumber) throws NoSuchAlgorithmException {
		String uTime = null;
		Date dt = new Date();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddhhmmssSSS");
		String uniqueTime = sdf.format(dt);
		uTime = aadhaarNumber + uniqueTime;
		MessageDigest md = MessageDigest.getInstance("MD5");
		md.update(uTime.getBytes());
		byte[] digest = md.digest();
		String myHash = DatatypeConverter.printHexBinary(digest).toUpperCase();
		return myHash;
	}

	public void validateUID(String uid, String type) throws RuntimeException {
		if ((null == uid) || ("".equals(uid))) {
			throw new ValueNotPassedException("Aadhaar number or vid is not passed.");
		}
		
		int uidLength =uid.trim().length();
		if ("A".equals(type.trim().toUpperCase())) {
			if ((uidLength > 12) || (uidLength < 12)) {
				throw new LengthMismatchException("Length of aadhaar number or vid is not valid.");
			}
		} else if ("V".equals(type.trim().toUpperCase())) {
			if ((uidLength > 16) || (uidLength < 16)) {
				throw new LengthMismatchException("Length of aadhaar number or vid is not valid.");
			}
		} else if ((uidLength > 72) || (uidLength < 72)) {
			throw new LengthMismatchException("Length of aadhaar number or vid is not valid.");
		}
	}

	public void validateTransactionId(String uniquereqid) throws RuntimeException {
		if ((uniquereqid == null) || ("".equals(uniquereqid))) {
			throw new ValueNotPassedException("Transaction Id is not passed.");
		}
	}

	public void validateToken(String token) throws RuntimeException {
		if ((token == null) || ("".equals(token))) {
			throw new ValueNotPassedException("Aadhaar Token is not passed.");
		}
	}
	
	
	public void validateDeviceInfiHash(String dih) throws RuntimeException {
		if ((dih == null) || ("".equals(dih))) {
			throw new ValueNotPassedException("Registerd device inforamation not passed.");
		}
	}
	
	public void validateOtp(String otp, String fpEnabled) throws Exception {
		if(!("Y".equalsIgnoreCase(fpEnabled) )){
			if ((otp.trim() == null) || ("".equals(otp.trim()))) {
				throw new ValueNotPassedException("One time password(OTP) is not passed.");
			} else {
				int otpLength = (int)Math.log10(Long.parseLong(otp.trim())) + 1;
				if (otpLength != 6){
					throw new LengthMismatchException("Length of One time password(OTP) is not valid.");
				}
			}			
		} else {
			if ((otp.trim() == null) || ("".equals(otp.trim()))) {
				throw new ValueNotPassedException("Biomatric data not passed properly.");
			}
		}
	}

	public String setAuthTypeForOTP(String authType) {
		if ((authType != null) && (!"".equals(authType))) {
			return authType.trim();
		}
		return "otpauth";
	}

	public String setAuthTypeForOTPAuthentication(String authType) {
		if ((authType != null) && (!"".equals(authType))) {
			return authType.trim();
		}
		return "auth";
	}

	public String setAuthTypeForDemoAuth(String authType) {
		if ((authType != null) && (!"".equals(authType))) {
			return authType.trim();
		}
		return "demoauth";
	}

	public String setAuthTypeForEkyc(String authType) {
		if ((authType != null) && (!"".equals(authType))) {
			return authType.trim();
		}
		return "kyc";
	}

	public String setResidentialConsent(String consent) {
		if ((consent != null) && (!"".equals(consent))) {
			return consent.toUpperCase().trim();
		}
		return "N";
	}
	
	
	public void validatePersonName(String personName) throws RuntimeException {
		if ((personName == null) || ("".equals(personName.trim()))) {
			throw new ValueNotPassedException("Person name is not passed.");
		}
	}
	
	public void validatePersonGender(String personGender) throws RuntimeException {
		if ((personGender == null) || ("".equals(personGender.trim()))) {
			throw new ValueNotPassedException("Person gender is not passed.");
		}
	}
	
	public void validatePersonDOB(String personDob) throws RuntimeException {
		if ((personDob == null) || ("".equals(personDob.trim()))) {
			throw new ValueNotPassedException("Person date of birth is not passed.");
		}
	}
	
	public void validatePhone(String phone) throws RuntimeException {
		if ((phone == null) || ("".equals(phone.trim()))) {
			throw new ValueNotPassedException("Phone number is not passed.");
		}
	}
	
	public void validatePincode(String pincode) throws RuntimeException {
		if ((pincode == null) || ("".equals(pincode.trim()))) {
			throw new ValueNotPassedException("Pincode is not passed.");
		}
	}

	public String createAPIKey(String KEYFORMAT, String VALUE) throws Exception {
		if (((KEYFORMAT == null) || ("".equals(KEYFORMAT))) && ((VALUE == null) || ("".equals(VALUE)))) {
			throw new RuntimeException("Error in creating client key.");
		}
		String password = new SimpleDateFormat(KEYFORMAT).format(new Date());
		return this.hmac.hmacSha256(password, VALUE);
	}
}
