/*
 * 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.ag.services.infrastructure.remote.voting;

import javax.validation.constraints.NotNull;
import javax.ws.rs.core.MediaType;

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.scytl.products.ov.commons.beans.domain.model.receipt.Receipt;
import com.scytl.products.ov.commons.infrastructure.remote.client.RestClientInterceptor;

import okhttp3.ResponseBody;

import retrofit2.Call;
import retrofit2.http.*;
import okhttp3.RequestBody;

/**
 * The Interface of authentication client for voting.
 */
public interface VotingWorkflowVotingClient {

    /** The Constant PARAMETER_VALUE_TENANT_ID. */
    public static final String PARAMETER_VALUE_TENANT_ID = "tenantId";

    /** The Constant PARAMETER_VALUE_ELECTION_EVENT_ID. */
    public static final String PARAMETER_VALUE_ELECTION_EVENT_ID = "electionEventId";

    /** The Constant PARAMETER_VALUE_VOTING_CARD_ID. */
    public static final String PARAMETER_VALUE_VOTING_CARD_ID = "votingCardId";

    /** The Constant PARAMETER_VALUE_CREDENTIAL_ID. */
    public static final String PARAMETER_VALUE_CREDENTIAL_ID = "credentialId";

    /** The Constant PARAMETER_PATH_INFORMATIONS. */
    public static final String PARAMETER_PATH_INFORMATIONS = "pathInformations";

    /** The Constant PARAMETER_PATH_INFORMATIONS. */
    public static final String PARAMETER_PATH_RECEIPT = "pathReceipt";

    /** The Constant PARAMETER_PATH_TOKENS. */
    public static final String PARAMETER_PATH_TOKENS = "pathTokens";

    /** The Constant PARAMETER_PATH_VOTES. */
    public static final String PARAMETER_PATH_VOTES = "pathVotes";

    /** The Constant PARAMETER_PATH_CONFIRMATIONS. */
    public static final String PARAMETER_PATH_CONFIRMATIONS = "pathConfirmations";

    /** The Constant PARAMETER_PATH_CHOICECODES. */
    public static final String PARAMETER_PATH_CHOICECODES = "pathChoicecodes";

    /** The Constant PARAMETER_PATH_CASTCODES. */
    public static final String PARAMETER_PATH_CASTCODES = "pathCastcodes";

    /** The Constant PARAMETER_AUTHENTICATION_TOKEN. */
    public static final String PARAMETER_AUTHENTICATION_TOKEN = "authenticationToken";

    /** The Constant X_FORWARDED_FOR. */
    public static final String PARAMETER_X_FORWARDED_FOR = "X-Forwarded-For";

    /** The Constant X_REQUEST_ID. */
    public static final String PARAMETER_X_REQUEST_ID = "X-Request-ID";

    @GET("{pathInformations}/tenant/{tenantId}/electionevent/{electionEventId}/credential/{credentialId}")
    Call<JsonObject> findInformationsByTenantElectionEventCredential(
            @Path(PARAMETER_PATH_INFORMATIONS) String pathInformations,
            @Path(PARAMETER_VALUE_TENANT_ID) String tenantId,
            @Path(PARAMETER_VALUE_ELECTION_EVENT_ID) String electionEventId,
            @Path(PARAMETER_VALUE_CREDENTIAL_ID) String credentialId,
            @NotNull @Header(PARAMETER_X_FORWARDED_FOR) String xForwardedFor,
            @NotNull @Header(PARAMETER_X_REQUEST_ID) String trackingId);

    @POST("{pathTokens}/tenant/{tenantId}/electionevent/{electionEventId}/credential/{credentialId}")
    Call<JsonObject> getAuthenticationToken(@Path(PARAMETER_PATH_TOKENS) String pathTokens,
            @Path(PARAMETER_VALUE_TENANT_ID) String tenantId,
            @Path(PARAMETER_VALUE_ELECTION_EVENT_ID) String electionEventId,
            @Path(PARAMETER_VALUE_CREDENTIAL_ID) String credentialId,
            @NotNull @Header(PARAMETER_X_FORWARDED_FOR) String xForwardedFor,
            @NotNull @Header(PARAMETER_X_REQUEST_ID) String trackingId,
            @NotNull @Body RequestBody challengeInformationJsonString);

    @POST("{pathConfirmations}/tenant/{tenantId}/electionevent/{electionEventId}/votingcard/{votingCardId}")
    Call<JsonObject> validateConfirmationMessage(@Path(PARAMETER_PATH_CONFIRMATIONS) String pathConfirmations,
            @Path(PARAMETER_VALUE_TENANT_ID) String tenantId,
            @Path(PARAMETER_VALUE_ELECTION_EVENT_ID) String electionEventId,
            @Path(PARAMETER_VALUE_VOTING_CARD_ID) String votingCardId,
            @NotNull @Header(PARAMETER_AUTHENTICATION_TOKEN) String authenticationTokenJsonString,
            @NotNull @Header(PARAMETER_X_FORWARDED_FOR) String xForwardedFor,
            @NotNull @Header(PARAMETER_X_REQUEST_ID) String trackingId,
            @NotNull @Body RequestBody confirmationInformationJsonString);

    @POST("{pathVotes}/tenant/{tenantId}/electionevent/{electionEventId}/votingcard/{votingCardId}")
    Call<JsonObject> validateVoteAndStore(@Path(PARAMETER_PATH_VOTES) String pathVotes,
            @Path(PARAMETER_VALUE_TENANT_ID) String tenantId,
            @Path(PARAMETER_VALUE_ELECTION_EVENT_ID) String electionEventId,
            @Path(PARAMETER_VALUE_VOTING_CARD_ID) String votingCardId,
            @NotNull @Header(PARAMETER_AUTHENTICATION_TOKEN) String authenticationTokenJsonString,
            @NotNull @Header(PARAMETER_X_FORWARDED_FOR) String xForwardedFor,
            @NotNull @Header(PARAMETER_X_REQUEST_ID) String trackingId, @NotNull @Body RequestBody voteJsonString);

    @GET("{pathVotes}/tenant/{tenantId}/electionevent/{electionEventId}/votingcard/{votingCardId}/verification-code")
    Call<ResponseBody> requestVerificationCode(@Path(PARAMETER_PATH_VOTES) String pathVotes,
            @Path(PARAMETER_VALUE_TENANT_ID) String tenantId,
            @Path(PARAMETER_VALUE_ELECTION_EVENT_ID) String electionEventId,
            @Path(PARAMETER_VALUE_VOTING_CARD_ID) String votingCardId,
            @NotNull @Header(PARAMETER_AUTHENTICATION_TOKEN) String authenticationTokenJsonString,
            @NotNull @Header(PARAMETER_X_FORWARDED_FOR) String xForwardedFor,
            @NotNull @Header(PARAMETER_X_REQUEST_ID) String trackingId);

    @POST("{pathVotes}/tenant/{tenantId}/electionevent/{electionEventId}/votingcard/{votingCardId}/vote-with-verification-code")
    Call<JsonObject> validateVoteWithVerificationCodeAndStore(@Path(PARAMETER_PATH_VOTES) String pathVotes,
            @Path(PARAMETER_VALUE_TENANT_ID) String tenantId,
            @Path(PARAMETER_VALUE_ELECTION_EVENT_ID) String electionEventId,
            @Path(PARAMETER_VALUE_VOTING_CARD_ID) String votingCardId,
            @NotNull @Header(PARAMETER_AUTHENTICATION_TOKEN) String authenticationTokenJsonString,
            @NotNull @Header(PARAMETER_X_FORWARDED_FOR) String xForwardedFor,
            @NotNull @Header(PARAMETER_X_REQUEST_ID) String trackingId, @NotNull @Body RequestBody voteJsonString);

    @GET("{pathChoicecodes}/tenant/{tenantId}/electionevent/{electionEventId}/votingcard/{votingCardId}")
    Call<JsonObject> getChoiceCodes(@Path(PARAMETER_PATH_CHOICECODES) String pathChoicecodes,
            @Path(PARAMETER_VALUE_TENANT_ID) String tenantId,
            @Path(PARAMETER_VALUE_ELECTION_EVENT_ID) String electionEventId,
            @Path(PARAMETER_VALUE_VOTING_CARD_ID) String votingCardId,
            @NotNull @Header(PARAMETER_AUTHENTICATION_TOKEN) String authenticationTokenJsonString,
            @NotNull @Header(PARAMETER_X_FORWARDED_FOR) String xForwardedFor,
            @NotNull @Header(PARAMETER_X_REQUEST_ID) String trackingId);

    @GET("{pathCastcodes}/tenant/{tenantId}/electionevent/{electionEventId}/votingcard/{votingCardId}")
    Call<JsonObject> getCastCodeMessage(@Path(PARAMETER_PATH_CASTCODES) String pathCastcodes,
            @Path(PARAMETER_VALUE_TENANT_ID) String tenantId,
            @Path(PARAMETER_VALUE_ELECTION_EVENT_ID) String electionEventId,
            @Path(PARAMETER_VALUE_VOTING_CARD_ID) String votingCardId,
            @NotNull @Header(PARAMETER_AUTHENTICATION_TOKEN) String authenticationTokenJsonString,
            @NotNull @Header(PARAMETER_X_FORWARDED_FOR) String xForwardedFor,
            @NotNull @Header(PARAMETER_X_REQUEST_ID) String trackingId);

    @POST("{pathVotes}/secured/tenant/{tenantId}/electionevent/{electionEventId}/votingcards/states")
    Call<JsonArray> getStatusOfVotingCards(@Path(PARAMETER_PATH_VOTES) String pathVotes,
            @Path(PARAMETER_VALUE_TENANT_ID) final String tenantId,
            @Path(PARAMETER_VALUE_ELECTION_EVENT_ID) final String electionEventId,
            @NotNull @Header(PARAMETER_X_FORWARDED_FOR) String xForwardedFor,
            @NotNull @Header(PARAMETER_X_REQUEST_ID) String trackingId,
            @NotNull @Header(RestClientInterceptor.HEADER_ORIGINATOR) String originator,
            @NotNull @Header(RestClientInterceptor.HEADER_SIGNATURE) String signature,
            @NotNull @Body RequestBody votingCardsJsonString);

    @GET("{pathVotes}/secured/tenant/{tenantId}/electionevent/{electionEventId}/votingcards/states/inactive")
    @Headers("Accept:" + MediaType.APPLICATION_OCTET_STREAM)
    @Streaming
    Call<ResponseBody> getIdAndStateOfInactiveVotingCards(@Path(PARAMETER_PATH_VOTES) String pathVotes,
            @Path(PARAMETER_VALUE_TENANT_ID) final String tenantId,
            @Path(PARAMETER_VALUE_ELECTION_EVENT_ID) final String electionEventId,
            @NotNull @Header(PARAMETER_X_FORWARDED_FOR) String xForwardedFor,
            @NotNull @Header(PARAMETER_X_REQUEST_ID) String trackingId,
            @NotNull @Header(RestClientInterceptor.HEADER_ORIGINATOR) String originator,
            @NotNull @Header(RestClientInterceptor.HEADER_SIGNATURE) String signature);

    @PUT("{pathVotes}/secured/tenant/{tenantId}/electionevent/{electionEventId}/votingcards/block")
    Call<JsonArray> blockVotingCards(@Path(PARAMETER_PATH_VOTES) String pathVotes,
            @Path(PARAMETER_VALUE_TENANT_ID) final String tenantId,
            @Path(PARAMETER_VALUE_ELECTION_EVENT_ID) final String electionEventId,
            @NotNull @Header(PARAMETER_X_FORWARDED_FOR) String xForwardedFor,
            @NotNull @Header(PARAMETER_X_REQUEST_ID) String trackingId,
            @NotNull @Header(RestClientInterceptor.HEADER_ORIGINATOR) String originator,
            @NotNull @Header(RestClientInterceptor.HEADER_SIGNATURE) String signature,
            @NotNull @Body RequestBody blockVotingCardsJsonString);

    @GET("{pathReceipt}/tenant/{tenantId}/electionevent/{electionEventId}/votingcard/{votingCardId}")
    Call<Receipt> getReceipt(@Path(PARAMETER_PATH_RECEIPT) String pathReceipts,
            @Path(PARAMETER_VALUE_TENANT_ID) String tenantId,
            @Path(PARAMETER_VALUE_ELECTION_EVENT_ID) String electionEventId,
            @Path(PARAMETER_VALUE_VOTING_CARD_ID) String votingCardId,
            @NotNull @Header(PARAMETER_AUTHENTICATION_TOKEN) String authenticationTokenJsonString,
            @NotNull @Header(PARAMETER_X_FORWARDED_FOR) String xForwardedFor,
            @NotNull @Header(PARAMETER_X_REQUEST_ID) String trackingId);

}
