/*
 * 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.sdm.infrastructure.electoralauthority;

import java.io.IOException;

import javax.json.JsonObject;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;

import com.scytl.products.ov.commons.ui.ws.rs.ObjectMappers;
import com.scytl.products.ov.commons.validation.ValidationResult;
import com.scytl.products.ov.sdm.domain.model.electoralauthority.ElectoralAuthorityUploadRepository;

/**
 * Implements the repository for electoral authority upload.
 */
@Repository
public class ElectoralAuthorityUploadRepositoryImpl implements ElectoralAuthorityUploadRepository {

	public static final String ADMIN_BOARD_ID_PARAM = "adminBoardId";

	private static final String ENDPOINT_CHECK_IF_EMPTY =
		"/electioneventdata/tenant/{tenantId}/electionevent/{electionEventId}/status";

	private static final Logger LOGGER = LoggerFactory.getLogger(ElectoralAuthorityUploadRepositoryImpl.class);

	private static final String ELECTION_EVENT_ID_PARAM = "electionEventId";

	private static final String TENANT_ID_PARAM = "tenantId";

	private static final String ELECTORAL_AUTHORITY_PARAM = "electoralAuthorityId";

	private static final String UPLOAD_ELECTION_EVENT_DATA_URL =
		"/electioneventdata/tenant/{tenantId}/electionevent/{electionEventId}/adminboard/{adminBoardId}";

	private static final String UPLOAD_ELECTORAL_DATA_VERIFICATION_CONTEXT_URL =
		"/electoraldata/tenant/{tenantId}/electionevent/{electionEventId}/electoralauthority/{electoralAuthorityId}/adminboard/{adminBoardId}";

	private static final String UPLOAD_ELECTORAL_DATA_ELECTION_INFORMATION_CONTEXT_URL =
		"/electoraldata/tenant/{tenantId}/electionevent/{electionEventId}/electoralauthority/{electoralAuthorityId}/adminboard/{adminBoardId}";

	@Value("${AU_URL}")
	private String authenticationURL;

	@Value("${EI_URL}")
	private String electionInformationURL;

	@Value("${VV_URL}")
	private String voteVerificationURL;

	@Value("${tenantID}")
	private String tenantId;

	@Override
	public boolean uploadAuthenticationContextData(String electionEventId, final String adminBoardId, JsonObject json) {

		WebTarget target = ClientBuilder.newClient().target(authenticationURL);
		Response response = target.path(UPLOAD_ELECTION_EVENT_DATA_URL).resolveTemplate(TENANT_ID_PARAM, tenantId)
			.resolveTemplate(ELECTION_EVENT_ID_PARAM, electionEventId).resolveTemplate(ADMIN_BOARD_ID_PARAM, adminBoardId)
			.request().post(Entity.entity(json.toString(), MediaType.APPLICATION_JSON_TYPE));

		return response.getStatus() == Response.Status.OK.getStatusCode();

	}

	@Override
	public boolean uploadElectionInformationContextData(String electionEventId, final String adminBoardId,
			JsonObject json) {

		WebTarget target = ClientBuilder.newClient().target(electionInformationURL);
		Response response = target.path(UPLOAD_ELECTION_EVENT_DATA_URL).resolveTemplate(TENANT_ID_PARAM, tenantId)
			.resolveTemplate(ELECTION_EVENT_ID_PARAM, electionEventId).resolveTemplate(ADMIN_BOARD_ID_PARAM, adminBoardId)
			.request().post(Entity.entity(json.toString(), MediaType.APPLICATION_JSON_TYPE));

		return response.getStatus() == Response.Status.OK.getStatusCode();

	}

	@Override
	public boolean uploadElectoralDataInVerificationContext(String electionEventId, String electoralAuthorityId,
			final String adminBoardId, JsonObject json) {

		WebTarget target = ClientBuilder.newClient().target(voteVerificationURL);
		Response response = target.path(UPLOAD_ELECTORAL_DATA_VERIFICATION_CONTEXT_URL)
			.resolveTemplate(TENANT_ID_PARAM, tenantId).resolveTemplate(ELECTION_EVENT_ID_PARAM, electionEventId)
			.resolveTemplate(ELECTORAL_AUTHORITY_PARAM, electoralAuthorityId)
			.resolveTemplate(ADMIN_BOARD_ID_PARAM, adminBoardId).request()
			.post(Entity.entity(json.toString(), MediaType.APPLICATION_JSON_TYPE));

		return response.getStatus() == Response.Status.OK.getStatusCode();
	}
	
	@Override
	public boolean uploadElectoralDataInElectionInformationContext(String electionEventId, String electoralAuthorityId,
			String adminBoardId, JsonObject json) {
		WebTarget target = ClientBuilder.newClient().target(electionInformationURL);
		Response response = target.path(UPLOAD_ELECTORAL_DATA_ELECTION_INFORMATION_CONTEXT_URL)
			.resolveTemplate(TENANT_ID_PARAM, tenantId).resolveTemplate(ELECTION_EVENT_ID_PARAM, electionEventId)
			.resolveTemplate(ELECTORAL_AUTHORITY_PARAM, electoralAuthorityId)
			.resolveTemplate(ADMIN_BOARD_ID_PARAM, adminBoardId).request()
			.post(Entity.entity(json.toString(), MediaType.APPLICATION_JSON_TYPE));

		return response.getStatus() == Response.Status.OK.getStatusCode();
	}

	/**
	 * Checks if the information is empty for the given election event
	 * 
	 * @param electionEvent - identifier of the electionevent
	 * @return
	 */
	@Override
	public boolean checkEmptyElectionEventDataInEI(String electionEvent) {
		Boolean result = Boolean.FALSE;
		WebTarget target = ClientBuilder.newClient().target(electionInformationURL + ENDPOINT_CHECK_IF_EMPTY);

		Response response = target.resolveTemplate(TENANT_ID_PARAM, tenantId)
			.resolveTemplate(ELECTION_EVENT_ID_PARAM, electionEvent).request(MediaType.APPLICATION_JSON).get();
		if (response.getStatus() == Response.Status.OK.getStatusCode()) {
			String json = response.readEntity(String.class);
			ValidationResult validationResult = new ValidationResult();
			try {
				validationResult = ObjectMappers.fromJson(json, ValidationResult.class);
			} catch (IOException e) {
				LOGGER.error("Error checking if a ballot box is empty", e);
			}
			result = validationResult.isResult();
		}
		return result;
	}

	@Override
	public boolean checkEmptyElectionEventDataInAU(String electionEvent) {
		Boolean result = Boolean.FALSE;
		WebTarget target = ClientBuilder.newClient().target(authenticationURL + ENDPOINT_CHECK_IF_EMPTY);

		Response response = target.resolveTemplate(TENANT_ID_PARAM, tenantId)
			.resolveTemplate(ELECTION_EVENT_ID_PARAM, electionEvent).request(MediaType.APPLICATION_JSON).get();
		if (response.getStatus() == Response.Status.OK.getStatusCode()) {
			String json = response.readEntity(String.class);
			ValidationResult validationResult = new ValidationResult();
			try {
				validationResult = ObjectMappers.fromJson(json, ValidationResult.class);
			} catch (IOException e) {
				LOGGER.error("Error checking if a ballot box is empty", e);
			}
			result = validationResult.isResult();
		}
		return result;
	}

}
