class IngPaymentInitiationService implements PaymentInitiationService {

    @Override
    public Response<PaymentInitationRequestResponse201> initiatePayment(PaymentService paymentService,
                                                                        PaymentProduct paymentProduct,
                                                                        RequestHeaders requestHeaders,
                                                                        RequestParams requestParams,
                                                                        Object body) {
        requireValid(validateInitiatePayment(paymentService, paymentProduct, requestHeaders, requestParams, body));

        switch (paymentService) {
            case PAYMENTS:
                if (body instanceof String) {
                    IngXmlPaymentProduct product = IngXmlPaymentProduct.of(paymentProduct);
                    return paymentInitiationApi.initiatePaymentXml(product,
                        requestHeaders.get(RequestHeaders.X_REQUEST_ID).orElse(null),
                        requestHeaders.get(RequestHeaders.TPP_REDIRECT_URI).orElse(null),
                        requestHeaders.get(RequestHeaders.PSU_IP_ADDRESS).orElse(null),
                        ingOauth2Service.getClientAuthentication(),
                        (String) body)
                        .map(mapper::map)
                        .map(this::rewriteLinks);
                }

                IngPaymentProduct product = IngPaymentProduct.of(paymentProduct);
                PaymentInitiationJson jsonBody = jsonMapper.convertValue(body, PaymentInitiationJson.class);
                return paymentInitiationApi.initiatePayment(product,
                    requestHeaders.get(RequestHeaders.X_REQUEST_ID).orElse(null),
                    requestHeaders.get(RequestHeaders.TPP_REDIRECT_URI).orElse(null),
                    requestHeaders.get(RequestHeaders.PSU_IP_ADDRESS).orElse(null),
                    ingOauth2Service.getClientAuthentication(),
                    mapper.map(jsonBody))
                    .map(mapper::map)
                    .map(this::rewriteLinks);

            case PERIODIC_PAYMENTS:
                if (body instanceof PeriodicPaymentInitiationMultipartBody) {
                    return paymentInitiationApi.initiatePeriodicPaymentXml(IngXmlPaymentProduct.of(paymentProduct),
                        requestHeaders.get(RequestHeaders.X_REQUEST_ID).orElse(null),
                        requestHeaders.get(RequestHeaders.TPP_REDIRECT_URI).orElse(null),
                        requestHeaders.get(RequestHeaders.PSU_IP_ADDRESS).orElse(null),
                        ingOauth2Service.getClientAuthentication(),
                        mapper.map((PeriodicPaymentInitiationMultipartBody) body))
                        .map(mapper::map)
                        .map(this::rewriteLinks);
                }

                return paymentInitiationApi.initiatePeriodicPayment(IngPaymentProduct.of(paymentProduct),
                    requestHeaders.get(RequestHeaders.X_REQUEST_ID).orElse(null),
                    requestHeaders.get(RequestHeaders.TPP_REDIRECT_URI).orElse(null),
                    requestHeaders.get(RequestHeaders.PSU_IP_ADDRESS).orElse(null),
                    ingOauth2Service.getClientAuthentication(),
                    mapper.map(jsonMapper.convertValue(body, PeriodicPaymentInitiationJson.class)))
                    .map(mapper::map)
                    .map(this::rewriteLinks);


            default:
                throw new UnsupportedOperationException(paymentService.toString());
        }
    }

    public  IngPaymentInitiationService(IngPaymentInitiationApi paymentInitiationApi,
                                       IngOauth2Service ingOauth2Service,
                                       LinksRewriter linksRewriter);

}