package be.ehealth.businessconnector.test.genericasync.helper;


import be.cin.nip.async.generic.Post;
import be.cin.nip.async.generic.PostResponse;
import be.ehealth.business.mycarenetcommons.builders.util.BlobUtil;
import be.ehealth.business.mycarenetdomaincommons.builders.BlobBuilder;
import be.ehealth.business.mycarenetdomaincommons.builders.BlobBuilderFactory;
import be.ehealth.business.mycarenetdomaincommons.domain.Blob;
import be.ehealth.business.mycarenetdomaincommons.domain.async.PostContent;
import be.ehealth.businessconnector.genericasync.encrypt.BusinessContentEncryptor;
import be.ehealth.business.mycarenetdomaincommons.util.WsAddressingUtil;
import be.ehealth.businessconnector.genericasync.builders.BuilderFactory;
import be.ehealth.businessconnector.genericasync.builders.ResponseObjectBuilder;
import be.ehealth.businessconnector.genericasync.exception.GenAsyncBusinessConnectorException;
import be.ehealth.businessconnector.genericasync.session.GenAsyncService;
import be.ehealth.businessconnector.genericasync.session.GenAsyncSessionServiceFactory;
import be.ehealth.technicalconnector.exception.ConnectorException;
import be.ehealth.technicalconnector.exception.TechnicalConnectorException;
import be.ehealth.technicalconnector.handler.domain.WsAddressingHeader;
import be.ehealth.technicalconnector.idgenerator.IdGeneratorFactory;
import be.ehealth.technicalconnector.utils.ConnectorXmlUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static be.ehealth.businessconnector.genericasync.domain.GenericAsyncConstants.POST_SOAP_ACTION;

/**
 * @author EHP
 */
public class PostTestHelper {

    private final Logger LOG = LoggerFactory.getLogger(PostTestHelper.class);
    
    private static final String DEFAULT_PLATFORM_NAME = "mycarenet";

    private String projectName;

    private String oa;
    
    private boolean test;
    
    private boolean withXades;
    
    private String platformName;

    private boolean encrypted;


    private PostTestHelper(Builder builder) {
        projectName = builder.projectName;
        oa = builder.oa;
        test = builder.test;
        withXades = builder.withXades;
        platformName = builder.platformName == null ? DEFAULT_PLATFORM_NAME : builder.platformName;
        encrypted = builder.encrypted;
    }

    public static Builder Builder() {
        return new Builder();
    }


    public void validateResponse(PostResponse responsePost) throws GenAsyncBusinessConnectorException, TechnicalConnectorException {
        ConnectorXmlUtils.dump(responsePost);
        ResponseObjectBuilder responseBuilder = BuilderFactory.getResponseObjectBuilder();
        responseBuilder.handlePostResponse(responsePost);
    }

    public PostResponse post(String serviceName, Post post) throws ConnectorException {
        GenAsyncService service = GenAsyncSessionServiceFactory.getGenAsyncService(serviceName);
        WsAddressingHeader header = WsAddressingUtil.createHeader(oa, POST_SOAP_ACTION);
        return service.postRequest(post, header);
    }

    public Post buildPostRequest(byte[] contentBytes, String messageName) throws TechnicalConnectorException {
        if(encrypted) {
            contentBytes = BusinessContentEncryptor.encrypt(projectName, contentBytes, messageName, platformName);
        }
        BlobBuilder blobBuilder = BlobBuilderFactory.getBlobBuilder(platformName, projectName, messageName);
        Blob blob = blobBuilder.build(contentBytes);
        blob.setMessageName(messageName);
        String commonInputReference = IdGeneratorFactory.getIdGenerator().generateId();
        byte[] xades = null;
        if (withXades && !encrypted) {
            xades = BlobUtil.generateXades(blob, projectName, platformName);
        }
        
        PostContent postContent = PostContent.Builder()
                .blob(blob)
                .commonInputReference(commonInputReference)
                .isTest(test)
                .messageName(messageName)
                .xades(xades)
                .build();
        
        return BuilderFactory.getRequestObjectBuilder(projectName).buildPostRequest(projectName, postContent);
    }

    public static final class Builder {
        private String projectName;
        private String oa;
        private boolean test = true;
        private boolean withXades;
        private String platformName = DEFAULT_PLATFORM_NAME;
        private boolean encrypted;
        
        private Builder() {
        }

        public Builder projectName(String projectName) {
            this.projectName = projectName;
            return this;
        }

        public Builder oa(String oa) {
            this.oa = oa;
            return this;
        }

        public Builder isTest(boolean test) {
            this.test = test;
            return this;
        }

        public Builder withXades(boolean withXades) {
            this.withXades = withXades;
            return this;
        }

        public Builder platformName(String platformName) {
            this.platformName = platformName;
            return this;
        }

        public Builder isEncrypted(boolean encrypted) {
            this.encrypted = encrypted;
            return this;
        }

        public PostTestHelper build() {
            return new PostTestHelper(this);
        }
    }
}
