package ru.uss.vstore.localserver;

import kz.gov.pki.kalkan.jce.provider.KalkanProvider;
import kz.gov.pki.kalkan.xmldsig.KncaXS;
import kz.gov.pki.provider.utils.XMLUtil;
import kz.gov.pki.provider.utils.model.SigningEntity;
import org.apache.cxf.annotations.WSDLDocumentation;
import ru.uss.vstore.constant.Namespaces;
import ru.uss.vstore.model.uform.UFormInfo;
import ru.uss.vstore.model.uform.version.UFormVersions;
import ru.uss.vstore.utils.UFormSignatureHelper;
import ru.ussgroup.security.trusty.TrustyUtils;

import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.security.auth.x500.X500PrivateCredential;
import java.security.Security;
import java.security.SignatureException;
import java.util.Collections;

/**
 * Вспомогательный сервис для работы с Универсальными Формами
 * Created by Ildar on 10.03.2016.
 */
@WebService(name = "UFormLocalService", serviceName = "UFormLocalService", targetNamespace = Namespaces.VSTORE)
@WSDLDocumentation("Локальный сервис для работы с Универсальными Формами")
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
public class VstoreLocalService {

    static {
        KncaXS.loadXMLSecurity();
    }

    @WebResult(name = "dataGenResponse")
    public UFormDataGenResponse generateData(@WebParam(name = "dataGenRequest") UFormDataGenRequest request) {
        UFormInfo uformInfo = CreateUForm.generate(request.getType());
        return response(uformInfo, request.getCertificatePath(), request.getCertificatePin());
    }

    @WebResult(name = "signatureGenResponse")
    public SignatureGenResponse generateSignature(@WebParam(name = "signatureGenRequest") SignatureGenRequest request) {
        return signatureResponse(request.getSignableData(), request.getCertificatePath(), request.getCertificatePin());
    }

    @WebResult(name = "documentXmlSignatureResponse")
    public DocumentXmlSignatureResponse generateDocumentXmlSignature(@WebParam(name = "documentXmlSignatureRequest") DocumentXmlSignatureRequest request) {
        return signatureXmlResponse(request.getSignableXmlData(), request.getCertificatePath(), request.getCertificatePin());
    }

    public SignatureGenResponse signatureResponse(String data, String certificatePath, String certificatePin) {
        try {
            String signature = signature(data, certificatePath, certificatePin);

            return new SignatureGenResponse(data, signature);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    public UFormDataGenResponse response(UFormInfo uformInfo, String certificatePath, String certificatePin) {
        try {
            String signature = signature(uformInfo.getuFormBody(), certificatePath, certificatePin);
            String version = UFormVersions.V1;

            return new UFormDataGenResponse(uformInfo.getuFormBody(), version, signature);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private String signature(String uFormBody, String certificatePath, String certificatePin) throws SignatureException {
        X500PrivateCredential credential = credential(certificatePath, certificatePin);
        return UFormSignatureHelper.sign(uFormBody, credential);
    }

    private X500PrivateCredential credential(String path, String pin) {
        return TrustyUtils.loadCredentialFromFile(path, pin);
    }

    public DocumentXmlSignatureResponse signatureXmlResponse(String xmlData, String certificatePath, String certificatePin) {
        try {
            X500PrivateCredential credential = credential(certificatePath, certificatePin);
            SigningEntity signingEntity = new SigningEntity(credential.getPrivateKey(), Collections.singletonList(credential.getCertificate()));
            return new DocumentXmlSignatureResponse(XMLUtil.createXmlSignature(signingEntity, xmlData, Security.getProvider(KalkanProvider.PROVIDER_NAME)));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}
