package cz.moneta.test.dsl.util.task.xyzmo;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import cz.moneta.test.dsl.Harness;
import cz.moneta.test.harness.endpoints.xyzmo.XyzmoEndpoint;
import cz.moneta.test.harness.support.rest.RawRestRequest;
import org.apache.commons.lang3.tuple.Pair;

import java.io.IOException;

public class XyzmoTasks {

    public static final XmlMapper JACKSON = new XmlMapper();
    private final Harness harness;

    public XyzmoTasks(Harness harness) {
        this.harness = harness;
    }

    public Pair<String, String> startSession() {
        String responseXml = RawRestRequest.customXmlBuilder(harness.getEndpoint(XyzmoEndpoint.class, 8080),
                "application/soap+xml;charset=UTF-8")
                .withPath("XyzmoController.asmx")
                .withHeader("SOAPAction", "http://schemas.designplus.cz/xc/daenerys/11/basic-web-services/xc_start_session")
                .withPayloadFromFile("xyzmo/01_XC_start.request.xml")
                .post()
                .extract("Body.xc_start_sessionResponse.xc_start_sessionResult")
                .asText();
        try {
            JsonNode xmlRoot = JACKSON.readTree(responseXml);
            String workstepId = xmlRoot.get("SessionTasks").get("TaskGroup").get("xyzmoWorkstepId").asText();
            String tokenId = xmlRoot.get("SessionState").get("tokenId").asText();
            return Pair.of(workstepId, tokenId);
        } catch (IOException e) {
            throw new IllegalStateException(String.format("failed to parse response xml: %s", responseXml), e);
        }
    }

    public RawRestRequest.Response signDocument(String workstepId) {
        return RawRestRequest.customXmlBuilder(harness.getEndpoint(XyzmoEndpoint.class, 47003),
                "application/soap+xml;charset=UTF-8")
                .withPath("WorkstepController.Process.asmx")
                .withHeader("SOAPAction", "http://com.xyzmo.server.workstepController.Process/SignWorkstepDocument_v2")
                .withPayload(String.format("<soap:Envelope xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\" " +
                        "xmlns:com=\"http://com.xyzmo.server.workstepController.Process/\">\n" +
                        "   <soap:Header/>\n" +
                        "   <soap:Body>\n" +
                        "      <com:SignWorkstepDocument_v2>\n" +
                        "         <!--Optional:-->\n" +
                        "         <com:workstepId>%s</com:workstepId>\n" +
                        "         <!--Optional:-->\n" +
                        "         <com:signatureConfig>&lt;!--Signature configuration--&gt;&lt;signature&gt;&lt;!--If" +
                        " given, a signature task with the same id is signed, otherwise a new signature field is " +
                        "added--&gt;&lt;sigFieldId&gt;2&lt;/sigFieldId&gt;&lt;!--If given, either the existing " +
                        "signature is reset to this position or a new signature is created. If no id, no image and no" +
                        " position is given, an invisible signature is added--&gt;&lt;sigFieldPosition&gt;&lt;!--The " +
                        "document reference number of the document this signature belongs to.--&gt;&lt;" +
                        "DocRefNumber&gt;1&lt;/DocRefNumber&gt;&lt;!--The elements x coordinate relative to the " +
                        "corner of the page in points. The referened corner is specified by " +
                        "'positionReferenceCorner'--&gt;&lt;positionX&gt;322.32&lt;/positionX&gt;&lt;!--The elements " +
                        "y coordinate relative to the corner of the page in points. The referened corner is specified" +
                        " by 'positionReferenceCorner'--&gt;&lt;positionY&gt;340.76&lt;/positionY&gt;&lt;!--The " +
                        "elements width in points--&gt;&lt;width&gt;195&lt;/width&gt;&lt;!--The elements height in " +
                        "points--&gt;&lt;height&gt;72&lt;/height&gt;&lt;!--The page number--&gt;&lt;positionPage&gt;" +
                        "3&lt;/positionPage&gt;&lt;!--Specifies which corner is the reference for the position. " +
                        "Possible Values: 'Lower_Left', 'Lower_Right', 'Upper_Left', Upper_Right'--&gt;&lt;" +
                        "positionReferenceCorner&gt;Lower_Left&lt;/positionReferenceCorner&gt;&lt;" +
                        "/sigFieldPosition&gt;&lt;!--Image embedded into the signature in base64 encoding--&gt;&lt;" +
                        "signatureImage&gt;" +
                        "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&lt;/signatureImage&gt;&lt;!--Additional signature parameters--&gt;&lt;signatureConfig&gt;&lt;!--Optional tag to set the reason in the adobe signature--&gt;&lt;reason&gt;&lt;/reason&gt;&lt;!--Optional tag to set the location in the adobe signature--&gt;&lt;location&gt;&lt;/location&gt;&lt;!--Optional tag to set the contact info in the adobe signature--&gt;&lt;contactInfo&gt;&lt;/contactInfo&gt;&lt;!--Optional tag localTimeInUtc: specify the signing time if not the local time of the server should be used. Format: yyyy-MM-ddThh:mm:ss.ffffZ--&gt;&lt;localTimeInUtc&gt;&lt;/localTimeInUtc&gt;&lt;signatureHashAlgorithm&gt;Sha256&lt;/signatureHashAlgorithm&gt;&lt;/signatureConfig&gt;&lt;!--The encrypted signature data container to embed into the signature--&gt;\n" +
                        "&lt;EncryptedSignatureDataContainer version=&quot;1.0&quot;&gt;\n" +
                        "&lt;EncryptedSessionKey Certificate=&quot;" +
                        "MIIEBTCCAu2gAwIBAgIDGxSxMA0GCSqGSIb3DQEBBQUAMGMxCzAJBgNVBAYTAkNaMSkwJwYDVQQDEyBJLkNBIC0gU3RhbmRhcmQgcm9vdCBjZXJ0aWZpY2F0ZTEpMCcGA1UEChMgUHJ2bmkgY2VydGlmaWthY25pIGF1dG9yaXRhIGEucy4wHhcNMTIwODIwMTA0MTE0WhcNMTMwODIwMTA0MTE0WjBeMQswCQYDVQQGEwJDWjEaMBgGA1UEAwwRR0UgUGFkIEVuY3J5cHRpb24xHDAaBgNVBAoME0dFIE1vbmV5IEJhbmssIGEucy4xFTATBgNVBAUTDElDQSAtIDczODY5MTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL2kPpAgL989nOHwDpxAHQlMT7riIT8fE7eGIZPpwYC5op53gUE+6zs6UFpRsh1oE11DfHLgwamxc1mNWnv5lg5tNSNrgAyiLutD/Ttv7tUA+NIw9wVemY9dpL2a7nzf48jds+SZASOTJnGr6j2cPYadMrCpOHyvJOkSBHlFQha4ByZWTSqXRtyDvaEf2VPQd5WK200SI9xp9PapXkgsvpek3DhGFjhUByjUkX0Y8Q6y0ioO+AFS9ae05B0IuZsIc+gkeodz8VCN6rGLh7SI6GOq+a2Hp2ZXzjxifnIWwu3zbAotWWM182mG0zUw/ctJjMKTpOJFTGtKrw1eNLF8V7kCAwEAAaOBxjCBwzAfBgNVHSMEGDAWgBTrN6S+uW9gF/vT/y1g4QQer8/G0zAdBgNVHQ4EFgQU2HK2uBAF5O5mJmltzucowUEewk8wGQYDVR0gBBIwEDAOBgwrBgEEAYG4SAEBAQMwCwYDVR0PBAQDAgTwMFkGA1UdHwRSMFAwJqAkoCKGIGh0dHA6Ly9zY3JsZHAxLmljYS5jei9zaWNhMDguY3JsMCagJKAihiBodHRwOi8vc2NybGRwMi5pY2EuY3ovc2ljYTA4LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAdw73djE4kaYppVHytBnlbJkBY8+LGW9vHZYkDEo/vKYRu4dM/SUFgTZyQrSrso95xh22HA+V+C5+/Lfpm97F/e1nohSX2RSWF9Co3P2UHryx+qvlWhemGc/nGTyc9mYSaq/Y/ImDsBNG/QqGUp7n6zRbjCSdBBKnVCsjpCqCjVN6u9GlCFD7qbL2XiGGNscF10usDi3ujQkvgITh2DsImQvpNTFkGLBvxW+RYwEiDEGx+1rEFh/Cc3JbFMuExvX4n2SyyUg1dtjPtvdpOOxDO059ID5iVQHHXAnntGPuErMI/86bIKqmFzb+l4rFaPQWjs1uOVC20EB1Ibr8knZJAw==&quot; Encoding=&quot;Base64&quot; Padding=&quot;PKCS#1 v1.5&quot;&gt;ecCFDy0UQ/RgZzhGpMQUNYM0ACK2Zops4w8xCD2K2Rd4cDrZQ8iHxiD5LYo0q56CsCk7iFrGgu57hvYjKGoahPhuf5mXZnDcPQg6W9UVjzDkcXRUk5AAZ6781WQM4vwV1W+2MrtSf1UKx1ypM/mtc1KUiazYb9bSUXn9UZ9q920/iBe04y9mKBD6EKfUoEyYooqwQc5tzlKZInlXXix1hnB5L/6Fhm/G5gWDMtBwv2J/EJ3y3a6tuwUUPxJ1xbFtoQHVEZloTv80TesNz5u/fWNrOjAU43C9PWsuy71AB70yMsljjN6reMo+EMSBIsUOaJOvSHW/Av0UqLCDkeGB6A==&lt;/EncryptedSessionKey&gt;\n" +
                        "&lt;EncryptedData CipherMode=&quot;CBC&quot; CipherSize=&quot;128&quot; Encoding=&quot;" +
                        "Base64&quot; IvSize=&quot;128&quot; KeySize=&quot;256&quot; PaddingMode=&quot;PKCS7&quot; " +
                        "SymmetricAlgorithm=&quot;AES&quot;&gt;" +
                        "2JIHQpGTUVb9fTfecbx8aP4Zlxj0j6LMhvS6yxhaXrfODRxnyXG1d/xCLCkcZoacUbeaYdeL" +
                        "+5Tcrg4jc9eyCIzdN1LzLGuUHr5VwJCqZkgmkFgeIxNblhMbrh/2CvL5waN/eyVKPjnyWr" +
                        "+swi4eyrtNg3t2GJhpQw2TCpId4Adwp4b8lZy54j52JcHcYldsfX031/Ax2VC5sA7TihDCbMgC" +
                        "+dqekCkgTzAjMXRqm9QXGNeK7dvxXfe1tMCzJaliNQ3rBd+nyrQJoIr9FDJwDEv6Z9O9DDMMnxfRMUr6T9RT" +
                        "/SAWby4qFlkLp9jYKutLBuLfnKU149wZBmS0TyqF8LoOD0RhYTa" +
                        "+ULNYVWfcrMzQPyqi5gMoWg0CANHnYnBibrXCTKJwj4GSTFexGceZygn3CVzuJD0QwpFZmAq7vlkGCy1jVbzx06JNA8xUrf6CKJw8JOHkPHgVJdECyDPSwducWQGAzD8ZSryHx+86yXV3PR/jL+5UiLagLFl7D9NtBlQpnJLCn0LwVi3azT7mI7Aj2ySZMt6bD8f6ARqgP4F+KbfBRmR5e0MW6Kp0hvVeJEmpHJpADcbwvc6ARTVdAqWCCgtHh6dN0caJP72w1mSJDbSGY9iM37UyXbN0JX9j+newKR8g49aA8FfZk9EuzJvHKmfB9a22JqJPwO1B01WPk9ZEwZ12N4+tTwijbtyPpUMDRahDPQsrU8aA6EpzLe+y3Bz5qp0fw8+lupsX/s8uKSx/9lsoH89s3YCaqpwYU5TV2WTLlcuS9Ei50NuVEZJ1zhIvrFxFkakIBSytKtT1pgsVNDStLyxZy4HzBemyDtAaDquY0MdHjOyTSZ+NSia2TUjdRvJixd01Re2IBZlEw9Qy3+zofPE7yOz7Py5gcx1VBST0EeJv14p8f7PQx232RqhP4AvZg4HrHXpifq3orObM5w6BySVgyaS03GkrF/YC+oZ989xzJa0F01N5yuU6Lk77AcjqJItAQexHujIxz4EUrZs1gRjrzD7dJeNCTEt6xwirWJpZIAoTGOthoehu+RQJIrhlxVrwLmWZkmPzbDv/nrxyi5F0NEgv35HAf2+79Td4lSmGzb0+UcTAv7W+uOvD83oRdaKpNBWZkzYZE+lqRNJJQGPhvY2fWUGaToBq84qhyEo+cbOGS4/rMpVlAoexnfVhIriwvlaT0xWb/MaiRf4DURI02Dj94KmH8LdqjNqCvEmsCtPAW/Q7Atp/sEtJba/QUQdVWxF/rwSrG+d1PF9uS1Vrn4+sYA/+kHyEBhdPbaehehLoQ8z4YcTTM9cJr60/+WlW80UsYregPCWPh/zCrk2LPGoOHra8TRcnEXpp3v6Z07cRJ1TnhnCvbdam3D5AmhBsYluEE0V9wvGKrClDAflwh+tB6cE5MrrVWYDvGZO8BldDoaHsKoD7ZV+JQHR6z0IDQVAQlMn4i7m5w52cZbWsUuvtAFa482dusEkwjB6CTXGw0l45nrDPvwJfcLbtfPdEsKtXUqr0X43lusc3GLfpEev5sVA4/6jmrwOAcqfHqzyVP3KT0Q==&lt;/EncryptedData&gt;\n" +
                        "&lt;/EncryptedSignatureDataContainer&gt;\n" +
                        "\t\t &lt;/signature&gt;</com:signatureConfig>\n" +
                        "         <!--Optional:-->\n" +
                        "         <com:transactionInformation>&lt;TransactionInformation&gt;&lt;ClientId&gt;XCF " +
                        "[Normal desktop]&lt;/ClientId&gt;&lt;ProductName&gt;SIGNificant WSI&lt;/ProductName&gt;&lt;" +
                        "ProductVersion&gt;3.0&lt;/ProductVersion&gt;&lt;ProductReleaseDate&gt;2015-01-01&lt;" +
                        "/ProductReleaseDate&gt;&lt;IpAddress&gt;freya&lt;/IpAddress&gt;&lt;" +
                        "/TransactionInformation&gt;</com:transactionInformation>\n" +
                        "      </com:SignWorkstepDocument_v2>\n" +
                        "   </soap:Body>\n" +
                        "</soap:Envelope>", workstepId))
                .post();
    }

    public RawRestRequest.Response getSessionStatus(String tokenId) {
        return RawRestRequest.customXmlBuilder(harness.getEndpoint(XyzmoEndpoint.class, 8080),
                "application/soap+xml;charset=UTF-8")
                .withPath("XyzmoController.asmx")
                .withHeader("SOAPAction", "http://schemas.designplus.cz/xc/daenerys/11/basic-web-services/xc_get_session_status")
                .withPayload(String.format("<soap:Envelope xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\" " +
                        "xmlns:bas=\"http://schemas.designplus.cz/xc/daenerys/11/basic-web-services\">\n" +
                        "   <soap:Header/>\n" +
                        "   <soap:Body>\n" +
                        "      <bas:xc_get_session_status>\n" +
                        "         <!--Optional:-->\n" +
                        "         <!--type: string-->\n" +
                        "         <bas:tokenId>%s</bas:tokenId>\n" +
                        "      </bas:xc_get_session_status>\n" +
                        "   </soap:Body>\n" +
                        "</soap:Envelope>", tokenId))
                .post();
    }

    public String getWorkstepId(String tokenId) {
        String responseXml = RawRestRequest.customXmlBuilder(harness.getEndpoint(XyzmoEndpoint.class, 8080),
                "application/soap+xml;charset=UTF-8")
                .withPath("XyzmoController.asmx")
                .withHeader("SOAPAction", "http://schemas.designplus" +
                        ".cz/xc/daenerys/11/basic-web-services/xc_get_session_status")
                .withPayload(String.format("<soap:Envelope xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\" " +
                        "xmlns:bas=\"http://schemas.designplus.cz/xc/daenerys/11/basic-web-services\">\n" +
                        "   <soap:Header/>\n" +
                        "   <soap:Body>\n" +
                        "      <bas:xc_get_session_status>\n" +
                        "         <bas:tokenId>%s</bas:tokenId>\n" +
                        "      </bas:xc_get_session_status>\n" +
                        "   </soap:Body>\n" +
                        "</soap:Envelope>", tokenId))
                .post()
                .extract("Body.xc_get_session_statusResponse.xc_get_session_statusResult")
                .asText();
        try {
            JsonNode xmlRoot = JACKSON.readTree(responseXml);
            return xmlRoot.get("SessionTasks").get("TaskGroup").get("xyzmoWorkstepId").asText();
        } catch (IOException e) {
            throw new IllegalStateException(String.format("failed to parse response xml: %s", responseXml), e);
        }
    }

    public RawRestRequest.Response setTaskResult(String tokenId) {
        return RawRestRequest.customXmlBuilder(harness.getEndpoint(XyzmoEndpoint.class, 8080),
                "application/soap+xml;charset=UTF-8")
                .withPath("XyzmoController.asmx")
                .withHeader("SOAPAction", "http://schemas.designplus.cz/xc/daenerys/11/basic-web-services/xc_set_task_result")
                .withPayload(String.format("<soap:Envelope xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\" " +
                        "xmlns:bas=\"http://schemas.designplus.cz/xc/daenerys/11/basic-web-services\">\n" +
                        "   <soap:Header/>\n" +
                        "   <soap:Body>\n" +
                        "      <bas:xc_set_task_result>\n" +
                        "         <bas:tokenId>%s</bas:tokenId>\n" +
                        "         <bas:taskId>1</bas:taskId>\n" +
                        "         <bas:result>0</bas:result>\n" +
                        "         <bas:resultText>OK</bas:resultText>\n" +
                        "         <bas:complete>1</bas:complete>\n" +
                        "      </bas:xc_set_task_result>\n" +
                        "   </soap:Body>\n" +
                        "</soap:Envelope>", tokenId))
                .post();
    }

    public RawRestRequest.Response finishWorkstep(String tokenId) {
        return RawRestRequest.customXmlBuilder(harness.getEndpoint(XyzmoEndpoint.class, 47003),
                "application/soap+xml;charset=UTF-8")
                .withPath("WorkstepController.Process.asmx")
                .withHeader("SOAPAction", "http://com.xyzmo.server.workstepController.Process/FinishWorkstep_v2")
                .withPayload(String.format("<soap:Envelope xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\" " +
                        "xmlns:com=\"http://com.xyzmo.server.workstepController.Process/\">\n" +
                        "   <soap:Header/>\n" +
                        "   <soap:Body>\n" +
                        "      <com:FinishWorkstep_v2>\n" +
                        "         <com:workstepId>#xcWorkstepId#</com:workstepId>\n" +
                        "         <com:transactionInformation>&lt;TransactionInformation&gt;&lt;ClientId&gt;XCF " +
                        "[Normal desktop]&lt;/ClientId&gt;&lt;ProductName&gt;SIGNificant WSI&lt;/ProductName&gt;&lt;" +
                        "ProductVersion&gt;3.0&lt;/ProductVersion&gt;&lt;ProductReleaseDate&gt;2015-01-01&lt;" +
                        "/ProductReleaseDate&gt;&lt;IpAddress&gt;freya&lt;/IpAddress&gt;&lt;" +
                        "/TransactionInformation&gt;</com:transactionInformation>\n" +
                        "      </com:FinishWorkstep_v2>\n" +
                        "   </soap:Body>\n" +
                        "</soap:Envelope>", tokenId))
                .post();
    }

}
