/*
 * 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.domain.service.impl;

import com.scytl.products.ov.commons.path.PathResolver;
import com.scytl.products.ov.commons.util.JsonUtils;
import com.scytl.products.ov.sdm.domain.model.ballotbox.BallotBoxRepository;
import com.scytl.products.ov.sdm.domain.model.config.CreateElectoralBoardKeyPairInput;
import com.scytl.products.ov.sdm.domain.model.generator.DataGeneratorResponse;
import com.scytl.products.ov.sdm.domain.service.ConfigConstants;
import com.scytl.products.ov.sdm.infrastructure.JsonConstants;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Implementation of a service which gives access to a generator of electoral board keys data from the configuration engine.
 */
@Service
public class ElectoralAuthorityDataGeneratorServiceImpl {

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

	@Autowired
	private BallotBoxRepository ballotBoxRepository;

	@Autowired
	private PathResolver pathResolver;

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

	@Value("${CREATE_ELECTORAL_BOARD_KEYS_URL}")
	private String createElectoralBoardKeysURL;

	public CreateElectoralBoardKeyPairInput generate(final String electoralAuthorityId, final String electionEventId) {

		DataGeneratorResponse result = validateInput(electoralAuthorityId, electionEventId);
		if (!result.isSuccessful()) {
			throw new IllegalStateException("invalid electoral authority and electionEventId");
		}

		// get all the ballot boxes related to the electoral authority
		String ballotBoxesResult = ballotBoxRepository.findByElectoralAuthority(electoralAuthorityId);

		JsonArray ballotBoxesList =
			JsonUtils.getJsonObject(ballotBoxesResult).getJsonArray(JsonConstants.JSON_ATTRIBUTE_NAME_RESULT);
		if (ballotBoxesList == null || ballotBoxesList.isEmpty()) {
			LOGGER.info("No ballot box found for election event with id-> " + electionEventId);
			result.setSuccessful(false);
			throw new IllegalStateException("ballotBoxes not found");
		}
		Path outputElectionEventPath = pathResolver.resolve(ConfigConstants.CONFIG_FILES_BASE_DIR).resolve(electionEventId);

		CreateElectoralBoardKeyPairInput createElectoralBoardKeyPairInput = new CreateElectoralBoardKeyPairInput();
		createElectoralBoardKeyPairInput.setOutputFolder(outputElectionEventPath.toString());
		createElectoralBoardKeyPairInput.setBallotMappings(createPairsBallotIdBallotBoxId(ballotBoxesList));

		return createElectoralBoardKeyPairInput;
	}

	// Validates the input data
	private DataGeneratorResponse validateInput(final String electoralAuthorityId, final String electionEventId) {
		DataGeneratorResponse response = new DataGeneratorResponse();
		// some basic validation of the input
		if (StringUtils.isBlank(electoralAuthorityId)) {
			response.setSuccessful(false);
			return response;
		}
		if (StringUtils.isBlank(electionEventId)) {
			response.setSuccessful(false);
			return response;
		}
		return response;
	}

	// create the set of pairs ballot id-ballot box id
	private Map<String, List<String>> createPairsBallotIdBallotBoxId(final JsonArray ballotBoxesList) {

		Map<String, List<String>> ballotId2BallotBoxListMap = new HashMap<String, List<String>>();
		for (int index = 0; index < ballotBoxesList.size(); index++) {
			JsonObject ballotBoxAsJson = ballotBoxesList.getJsonObject(index);
			String ballotId = ballotBoxAsJson.getJsonObject(JsonConstants.JSON_ATTRIBUTE_NAME_BALLOT)
				.getString(JsonConstants.JSON_ATTRIBUTE_NAME_ID);
			String ballotBoxId = ballotBoxAsJson.getString(JsonConstants.JSON_ATTRIBUTE_NAME_ID);
			if (ballotId2BallotBoxListMap.containsKey(ballotId)) {
				List<String> ballotBoxIdList = ballotId2BallotBoxListMap.get(ballotId);
				ballotBoxIdList.add(ballotBoxId);
			} else {
				List<String> ballotBoxIdList = new ArrayList<String>();
				ballotBoxIdList.add(ballotBoxId);
				ballotId2BallotBoxListMap.put(ballotId, ballotBoxIdList);
			}
		}

		return ballotId2BallotBoxListMap;
	}

	/**
	 * Generates a WebTarget client
	 *
	 * @return
	 */
	public WebTarget createWebClient() {
		return ClientBuilder.newClient().target(createElectoralBoardKeysURL);
	}

}
