package be.iminds.ilabt.jfed.highlevel.stitcher;

import be.iminds.ilabt.jfed.lowlevel.CredentialException;
import be.iminds.ilabt.jfed.lowlevel.SfaCredential;
import be.iminds.ilabt.jfed.lowlevel.TestCertHelper;
import be.iminds.ilabt.jfed.lowlevel.connection.MockReplyLibrary;
import be.iminds.ilabt.jfed.lowlevel.connection.MockSfaConnection;
import be.iminds.ilabt.jfed.util.GeniUrn;
import org.apache.xmlrpc.XmlRpcRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.Map;
import java.util.Objects;

/**
 * TestStitchingAMv2
 */
public class TestStitchingSAServer extends MockSfaConnection.AbstractMockXmlRpcReply {
    private final static Logger LOG = LoggerFactory.getLogger(TestStitchingSAServer.class);

    private static int globalIndex = 0;

    protected final String serverUrl;

    protected final String saUrnString;
    protected final GeniUrn saUrn;
    protected final String saHostname;

    protected final TestCertHelper testCertHelper;

    public TestStitchingSAServer(String serverUrl, String saUrnString, String saHostname, TestCertHelper testCertHelper) {
        this.serverUrl = serverUrl;
        this.saHostname = saHostname;
        this.saUrnString = saUrnString;
        try {
            this.saUrn = new GeniUrn(saUrnString);
        } catch (GeniUrn.GeniUrnParseException e) {
            throw new RuntimeException(e);
        }

        this.testCertHelper = testCertHelper;
    }

    @Override
    public MockSfaConnection.MockXmlRpcAnswer matches(XmlRpcRequest request) {
        if (!Objects.equals(MockReplyLibrary.getServerUrl(request), serverUrl))
            return null;

        if (Objects.equals(request.getMethodName(), "GetCredential") && request.getParameterCount() >= 0) {

            String targetUrn;
            if (request.getParameterCount() == 0)
                targetUrn = TestCertHelper.userUrn;
            else {
                Map ht = (Map) request.getParameter(0);
                targetUrn = (String) ht.get("urn");
            }

            X509Certificate ownerCert = testCertHelper.saCert;
            X509Certificate targetCert = testCertHelper.userCert;
            X509Certificate signerCert = testCertHelper.authority1Cert;
            PrivateKey signerPrivateKey = testCertHelper.authority1Keys.getSshPrivateKey();
            Date expireDate = Date.from(Instant.now().plus(1, ChronoUnit.DAYS));
            String privilegeName = "*";
            boolean canDelegate = true;
            String credentialjFedName = "Test Credential for Test User";
            SfaCredential cred = null;
            try {
                cred = SfaCredential.create(
                        "privilege",
                        saUrnString/*ownerUrn*/, targetUrn,
                        ownerCert, targetCert,
                        signerCert, signerPrivateKey,
                        expireDate, privilegeName, canDelegate,
                        credentialjFedName);
            } catch (CredentialException e) {
                LOG.debug("Error creating test credential", e);
                throw new RuntimeException(e);
            }
            String credentialXml = cred.getCredentialXml();

            return new MockSfaConnection.MockXmlRpcAnswer(TestStitchingXmlRpcHelper.wrapSuccessXmlRpcSAReply(TestStitchingXmlRpcHelper.encodeXmlRpcString(credentialXml)));
        }
        return null;
    }
}
