/*
 * 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.vv.ui.ws.rs.application.operation;

import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.IOException;

import com.scytl.products.oscore.logging.core.provider.TransactionInfoProvider;
import com.scytl.products.ov.commons.beans.exceptions.ApplicationException;
import com.scytl.products.ov.commons.beans.exceptions.ResourceNotFoundException;
import com.scytl.products.ov.commons.tracking.TrackIdInstance;
import com.scytl.products.ov.commons.ui.Constants;
import com.scytl.products.ov.commons.ui.ws.rs.ObjectMappers;
import com.scytl.products.ov.commons.util.HttpRequestService;
import com.scytl.products.ov.vv.domain.model.verificationset.VerificationSet;
import com.scytl.products.ov.vv.domain.model.verificationset.VerificationSetData;
import com.scytl.products.ov.vv.domain.model.verificationset.VerificationSetEntity;
import com.scytl.products.ov.vv.domain.model.verificationset.VerificationSetRepository;

/**
 * Service which offers the possibility of getting voter verifications sets from the system.
 */
@Path("/verificationsets")
@Stateless
public class VerificationSetResource {

    // The name of the parameter value tenant id.
    private static final String PARAMETER_VALUE_TENANT_ID = "tenantId";

    // The name of the parameter value verification card id.
    private static final String PARAMETER_VALUE_VERIFICATION_CARD_SET_ID = "verificationCardSetId";

    // String which defines the resource.
    private static final String RESOURCE = "VERIFICATIONSET";

    // The name of the parameter value election event id.
    private static final String PARAMETER_VALUE_ELECTION_EVENT_ID = "electionEventId";

    // The constant for the error code "mandantory.field".
    private static final String ERROR_CODE_MANDATORY_FIELD = "mandatory.field";

    // The constant for the message "Verification card id is null".
    private static final String VERIFIATION_CARD_SET_ID_IS_NULL = "Verification card set id is null";

    // The constant for the message "Election event id is null".
    private static final String ELECTION_EVENT_ID_IS_NULL = "Election event id is null";

    // The constant for the message "Tenant id is null".
    private static final String TENANT_ID_IS_NULL = "Tenant id is null";

    @Inject
    private VerificationSetRepository verificationSetDataRepository;
    // The track id instance
    @Inject
    private TrackIdInstance tackIdInstance;
    @Inject
    private TransactionInfoProvider transactionInfoProvider;
    @Inject
    private HttpRequestService httpRequestService;

    /**
     * Returns a credential and verification data for a given tenant, election event and verification card.
     *
     * @param trackingId            The track id to be used for logging purposes.
     * @param tenantId              The tenant identifier.
     * @param electionEventId       The election event identifier.
     * @param verificationCardSetId The verification card identifier.
     * @param request               The http servlet request.
     * @return a credential and verification data.
     * @throws ResourceNotFoundException If voter information is not found.
     * @throws IOException                Conversion exception from object to json. Material data.
     *                                    For example, both credential and verification data are null.
     *
     * @throws com.scytl.products.ov.commons.beans.exceptions.ApplicationException if one of the input parameters is null.
     */
    @Path("/tenant/{tenantId}/electionevent/{electionEventId}/verificationcardset/{verificationCardSetId}")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Response getVoterInformation(@HeaderParam(Constants.PARAMETER_HEADER_X_REQUEST_ID) String trackingId,
                                        @PathParam(PARAMETER_VALUE_TENANT_ID) String tenantId,
                                        @PathParam(PARAMETER_VALUE_ELECTION_EVENT_ID) String electionEventId,
                                        @PathParam(PARAMETER_VALUE_VERIFICATION_CARD_SET_ID) String verificationCardSetId,
                                        @Context HttpServletRequest request)
        throws IOException, ResourceNotFoundException, ApplicationException {
        // set the track id to be logged
        tackIdInstance.setTrackId(trackingId);

        // transaction id generation
        transactionInfoProvider.generate(tenantId, httpRequestService.getIpClientAddress(request),
            httpRequestService.getIpServer(request));

        // in case something from the input is not valid, it throws an exception
        validateInput(tenantId, electionEventId, verificationCardSetId);

        VerificationSetEntity verification = verificationSetDataRepository
            .findByTenantIdElectionEventIdVerificationCardSetId(tenantId, electionEventId, verificationCardSetId);

        // convert from string
        VerificationSetData verificationSetData = ObjectMappers.fromJson(verification.getJSON(), VerificationSetData.class);

        // build the result
        VerificationSet verificationSet = new VerificationSet();
        verificationSet.setId(verification.getVerificationCardSetId());
        verificationSet.setData(verificationSetData);
        verificationSet.setSignature(verification.getSignature());

        return Response.ok().entity(verificationSet).build();
    }

    // Validate input parameters.
    private void validateInput(String tenantId, String electionEventId, String verificationCardId)
        throws ApplicationException {
        if (tenantId == null) {
            throw new ApplicationException(TENANT_ID_IS_NULL, RESOURCE, ERROR_CODE_MANDATORY_FIELD,
                PARAMETER_VALUE_TENANT_ID);
        }
        if (electionEventId == null) {
            throw new ApplicationException(ELECTION_EVENT_ID_IS_NULL, RESOURCE, ERROR_CODE_MANDATORY_FIELD,
                PARAMETER_VALUE_ELECTION_EVENT_ID);
        }
        if (verificationCardId == null) {
            throw new ApplicationException(VERIFIATION_CARD_SET_ID_IS_NULL, RESOURCE, ERROR_CODE_MANDATORY_FIELD,
                PARAMETER_VALUE_VERIFICATION_CARD_SET_ID);
        }
    }
}
