/*
 * Copyright 2018 Scytl Secure Electronic Voting SA
 *
 * All rights reserved
 *
 * See our extended copyright notice in *file 'Copyright.txt' which is part of this source code package
 */
package com.scytl.products.ov.vm.domain.model.information;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.List;

import javax.ejb.Stateless;
import javax.inject.Inject;

import org.slf4j.Logger;

import com.scytl.products.oscore.logging.api.domain.Level;
import com.scytl.products.oscore.logging.api.domain.LogContent;
import com.scytl.products.oscore.logging.api.writer.SecureLoggingWriter;
import com.scytl.products.ov.commons.beans.exceptions.ResourceNotFoundException;
import com.scytl.products.ov.commons.tracking.TrackIdInstance;
import com.scytl.products.ov.vm.infrastructure.log.VoterMaterialLogConstants;
import com.scytl.products.ov.vm.infrastructure.log.VoterMaterialLogEvents;

/**
 * The Class VoterInformationService.
 */
@Stateless
public class VoterInformationService {

	/** The log. */
	@Inject
	private Logger LOG;

	/** The track id instance. */
	@Inject
	private TrackIdInstance trackIdInstance;

	/** The voter information repository. */
	@Inject
	private VoterInformationRepository voterInformationRepository;

	/** The secure logger writer. */
	@Inject
	private SecureLoggingWriter secureLoggerWriter;

	/** The Constant SQL_ESCAPE_CHARACTER. */
	private static final char SQL_ESCAPE_CHARACTER = '~';

	/**
	 * Search voter information.
	 *
	 * @param tenantId the tenant id
	 * @param electionEventId the election event id
	 * @param idSearchTerm the voting Card id
	 * @param pageNumber the page number
	 * @param pageSize the page size
	 * @return the list
	 * @throws ResourceNotFoundException the resource not found exception
	 * @throws UnsupportedEncodingException the unsupported encoding exception
	 */
	public List<VoterInformation> searchVoterInformation(final String tenantId, final String electionEventId,
			String idSearchTerm, final int pageNumber, final int pageSize)
					throws ResourceNotFoundException, UnsupportedEncodingException {

		LOG.info("Searching the voting cards for tenant: {} election event: {} and id search term: {}.", tenantId,
			electionEventId, idSearchTerm);

		String idSearchTermDecoded = decodeAnySpecialCharactersBeforeSearch(idSearchTerm);

		LOG.info("Term after decode: {}.", idSearchTermDecoded);

		// search the voterInformation for given search terms.
		try {
			List<VoterInformation> voterInformation = voterInformationRepository
					.findByTenantIdElectionEventIdAndSearchTerms(tenantId, electionEventId, idSearchTermDecoded,
							pageNumber, pageSize);

			LOG.info("Credential data for tenant: {} election event: {} found.", tenantId, electionEventId);

			return voterInformation;
		} catch (ResourceNotFoundException e) {
			// VoterInformation data not found
			secureLoggerWriter.log(Level.ERROR, new LogContent.LogContentBuilder()
				.logEvent(VoterMaterialLogEvents.VOTER_INFORMATION_NOT_FOUND).objectId("N/A").user("N/A")
				.electionEvent(electionEventId)
				.additionalInfo(VoterMaterialLogConstants.TRACK_ID, trackIdInstance.getTrackId())
				.additionalInfo(VoterMaterialLogConstants.ERR_DESC, "Resource not found in the VOTER_INFORMATION table.")
				.createLogInfo());

			throw e;
		}
	}

	/**
	 * Gets the count of voting cards.
	 *
	 * @param tenantId the tenant id
	 * @param electionEventId the election event id
	 * @param idSearchTerm the id search term
	 * @return the count of voting cards
	 * @throws ResourceNotFoundException the resource not found exception
	 * @throws UnsupportedEncodingException the unsupported encoding exception
	 */
	public long getCountOfVotingCardsForSearchTerms(final String tenantId, final String electionEventId,
			String idSearchTerm) throws ResourceNotFoundException, UnsupportedEncodingException {

		String idSearchTermDecoded = decodeAnySpecialCharactersBeforeSearch(idSearchTerm);

		LOG.info("Counting the voting cards for tenant: {} election event: {} and id search term: {}.", tenantId,
			electionEventId, idSearchTermDecoded);

		return voterInformationRepository.countByTenantIdElectionEventIdAndSearchTerms(tenantId, electionEventId,
				idSearchTermDecoded);
	}

	/**
	 * Decode any special characters before search.
	 *
	 * @param term1 the term1
	 * @return the string
	 * @throws UnsupportedEncodingException the unsupported encoding exception
	 */
	private String decodeAnySpecialCharactersBeforeSearch(final String term1) throws UnsupportedEncodingException {
		return URLDecoder.decode(term1, "UTF-8").replaceAll("~", SQL_ESCAPE_CHARACTER + "~")
			.replaceAll("_", SQL_ESCAPE_CHARACTER + "_").replaceAll("percentage", SQL_ESCAPE_CHARACTER + "%");
	}
}
