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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.NotNull;
import javax.ws.rs.Consumes;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
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.domain.model.authentication.AuthenticationToken;
import com.scytl.products.ov.commons.beans.exceptions.ValidationException;
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.commons.util.ValidationUtils;
import com.scytl.products.ov.ei.services.domain.model.confirmation.ConfirmationInformation;
import com.scytl.products.ov.ei.services.domain.model.confirmation.ConfirmationInformationResult;
import com.scytl.products.ov.ei.services.domain.service.confirmation.ConfirmationMessageValidationService;

/**
 * The endpoint for confirmation messages
 */
@Path(ConfirmationMessageResource.RESOURCE_PATH)
@Stateless
public class ConfirmationMessageResource {

    static final String RESOURCE_PATH = "/confirmations";

    static final String VALIDATE_CONFIRMATION_MESSAGE_PATH =
        "/tenant/{tenantId}/electionevent/{electionEventId}/votingcard/{votingCardId}";

    // The authentication token parameter
    private static final String AUTHENTICATION_TOKEN = "authenticationToken";

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

    // The name of the parameter value voting card id.
    private static final String PARAMETER_VALUE_VOTING_CARD_ID = "votingCardId";

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

    // The confirmation message validation service
    @Inject
    private ConfirmationMessageValidationService confirmationMessageValidationService;

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

    @Inject
    private TransactionInfoProvider transactionInfoProvider;

    @Inject
    private HttpRequestService httpRequestService;

    private static final Logger LOG = LoggerFactory.getLogger(ConfirmationMessageResource.class);


    /**
     * Receives a confirmation message with additional information , and
     * validates this information.
     *
     * @param tenantId
     *            - Tenant identifier
     * @param electionEventId
     *            - election event identifier
     * @param votingCardId
     *            - voting card identifier
     * @param confirmationInformation
     *            - confirmation information to be validated
     * @param authenticationTokenJsonString
     *            - the authentication token
     * @param trackingId
     *            - the request id for logging purposes
     * @param request
     *            - the http servlet request.
     * @return the result of the validation
     */
    @POST
    @Consumes(javax.ws.rs.core.MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    @Path(ConfirmationMessageResource.VALIDATE_CONFIRMATION_MESSAGE_PATH)
    public Response validateConfirmationMessage(@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_VOTING_CARD_ID) String votingCardId,
            ConfirmationInformation confirmationInformation,
            @NotNull @HeaderParam(AUTHENTICATION_TOKEN) String authenticationTokenJsonString,
            @Context HttpServletRequest request) {

        // set the track id to be logged
        trackIdInstance.setTrackId(trackingId);

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

        AuthenticationToken authenticationToken;
        try {
            // convert from json to object
            authenticationToken = ObjectMappers.fromJson(authenticationTokenJsonString, AuthenticationToken.class);

            // validate auth token
            ValidationUtils.validate(authenticationToken);
        } catch (IOException | IllegalArgumentException | ValidationException e) {
            LOG.error("Invalid authentication token format.", e);
            return Response.status(Response.Status.UNAUTHORIZED).build();
        }

        ConfirmationInformationResult result = confirmationMessageValidationService.validateConfirmationMessage(
            tenantId, electionEventId, votingCardId, confirmationInformation, authenticationToken);
        return Response.ok().entity(result).build();
    }
}
