#region Header

/*
 * Copyright (c) eHealth
 */

#endregion Header

/**
 * IntegrationTest for KGSSServiceIntegrationTest
 */
namespace be.ehealth.technicalconnector.service.kgss
{
    using System;
    using System.Collections.Generic;
    using System.Text;

    using be.ehealth.technicalconnector.config;
    using be.ehealth.technicalconnector.service.etee.domain;
    using be.ehealth.technicalconnector.service.keydepot;
    using be.ehealth.technicalconnector.service.keydepot.impl;
    using be.ehealth.technicalconnector.service.kgss;
    using be.ehealth.technicalconnector.service.kgss.impl;
    using be.ehealth.technicalconnector.service.sts;
    using be.ehealth.technicalconnector.service.sts.domain;
    using be.ehealth.technicalconnector.service.sts.impl;
    using be.ehealth.technicalconnector.service.sts.security;
    using be.ehealth.technicalconnector.service.sts.security.impl;
    using be.ehealth.technicalconnector.session;
    using be.ehealth.technicalconnector.utils;
    using be.ehealth.technicalconnector.utils.net;
    using be.fgov.ehealth.etee.crypto.utils;
    using be.fgov.ehealth.etee.kgss._1_0.protocol;
    using be.fgov.ehealth.etkdepot._1_0.protocol;

    using java.lang;
    using java.util;

    using NUnit.Framework;

    using org.w3c.dom;

    /**
     * Key Generation and Storage Service Integration Tests
     * This set of tests show the use of KGSS through the use of the Technical Connector.
     */
    [TestFixture]
    class KGSSServiceIntegrationTest : be.ehealth.technicalconnector.session.AbstractServiceIntegrationTest
    {
        #region Methods

        /**
         * Request KGSS to generate a new key with a predefined Access Control List.
         *
         * The GetNewKey methods required the following parameters:
         * - Credential: the credentials used to secure the web service call
         * - ETK of KGSS, used to seal the request to KGSS
         * - ETK of your application, used by KGSS to seal the response.
         * - Decryption keys from your keystore, needed by the eHealth Crypto Framework to seal and unseal data
         *
         * The following steps are executed:
         *  1. retrieve the credential
         *  2a. retrieve the ETK of KGSS
         *  2b. retrieve the ETK of your application
         *  3.  Use the eHealth Crypto Framework to retrieve the decryption keys
         *  4.  Request new key from KGSS
         *
         */
        [Test]
        public void T001_testGetNewKey()
        {
            GetNewKeyResponseContent response = retrieveResponseForTest();

            /*
             * Verify the response
             */
            // check if there is a response returned from the eHealth connector framework
            Assert.IsNotNull(response);
            // check the key identifier of the generated key
            Assert.IsNotNull(response.getNewKeyIdentifier());
        }

        /**
         * Retrieves a previously generated key from KGSS. The test will try to retrieve the key generated in the first test (testGetNewKey) The
         * GetKey operation is secured by means of a SAML Assertion / Secured Token, because of this a call to STS is needed to retrieve an SAML
         * Assertion / Secured Token.
         *
         * The GetKey methods required the following parameters: - authentication credentials: the credentials used to authenticate against STS,
         * usually your eID - service credentials: the credentials used to sign each succeeding request to an STS secured eHealth web service,
         * usually an eHealth issued certificate - Secure Token: the token received from STS - ETK of KGSS, used to seal the request to KGSS -
         * ETK of your application, used by KGSS to seal the response. - Decryption keys from your keystore, needed by the eHealth Crypto
         * Framework to seal and unseal data
         *
         * The following steps are executed: 1a. retrieve the authentication credential for the STS call 1b. retrieve the service credential for
         * the STS call 2. do the STS call to get an Secure Token 3a. retrieve the ETK of KGSS 3b. retrieve the ETK of your application 4. Use
         * the eHealth Crypto Framework to retrieve the decryption keys 5. retrieve the key from KGSS
         *
         * @throws TechnicalConnectorException the technical connector exception
         * @throws KeyStoreException key store exception
         * @throws NoSuchAlgorithmException no such algorithm exception
         */
        [Test]
        public void testGetKey()
        {
            GetNewKeyResponseContent responseToRetrieveKeyIdentifier = retrieveResponseForTest();

            byte[] keyIdentifier = responseToRetrieveKeyIdentifier.getNewKeyIdentifier();
            /*
             * Set the values to use in this test
             */
            // 1a. retrieve the authentication credential for the STS call. usually your eID (retrieved from property file)
            Credential authentication = new KeyStoreCredential(getSessionProps().getProperty("test.keystore.location"), getSessionProps().getProperty("test.keystore.alias"), getSessionProps().getProperty("test.keystore.password"));

            // 1b. retrieve the service credential for the STS call. usually an eHealth certificate (retrieved from property file)
            Credential service = new KeyStoreCredential(getSessionProps().getProperty("test.keystore.location"), getSessionProps().getProperty("test.keystore.alias"), getSessionProps().getProperty("test.keystore.password"));

            // 2. do the STS call to get an Secure Token (see Sts Service Integration Test for a full description of this service)
            Element token = Session.getInstance().getSession().getSAMLToken().getAssertion();

            // 3a. retrieve the ETK of KGSS (used to seal the request)
            byte[] kgssEtk = getKgssEtk();

            // 3b. retrieve the ETK of your application (inserted into the request, to seal the response)
            byte[] myEtk = getSystemEtk();

            //
            // 4. Use the eHealth Crypto Framework to retrieve the decryption keys
            //
            // load in the keystoremanager to be able to easily work with the keystores
            KeyStoreInfo ksInfo = new KeyStoreInfo(getSessionProps().getProperty("test.keystore.location"), getSessionProps().getProperty("test.keystore.password").ToCharArray(), getSessionProps().getProperty("test.keystore.alias"), getSessionProps().getProperty("test.keystore.password").ToCharArray());
            KeyStoreManager encryptionKeystoreManager = new KeyStoreManager(ksInfo.getKeystorePath(), ksInfo.getKeystorePassword());
            // use the eHealth Crypto Framework to get the decryption keys, it will need the keystore and the password for the private keys
            Map decryptionKeys = KeyManager.getDecryptionKeys(encryptionKeystoreManager.getKeyStore(), ksInfo.getKeystorePassword());

            /*
             * Create request
             */
            GetKeyRequestContent content = new GetKeyRequestContent();
            // set the etk of the sending application
            content.setETK(myEtk);
            // set the key identifier of the key to retrieve
            content.setKeyIdentifier(keyIdentifier);

            /*
             * 5. retrieve the key from KGSS Invoke the technical connector framework's KGSS Service's getKey operation
             */
            KgssService kgss = ServiceFactory.getKgssService();

            GetKeyResponseContent response = kgss.getKey(content, authentication, service, token, decryptionKeys, kgssEtk);

            /*
             * Verify the response
             */
            // check the retrieved key
            Assert.IsNotNull(response.getKey());
        }

        /**
         * Helper method for GetNewKey and GetKey. Returns the ETK of KGSS
         *
         * @return the ETK
         * @throws TechnicalConnectorException when a exception occurs
         */
        private byte[] getKgssEtk()
        {
            KeyDepotManager manager = KeyDepotManagerFactory.getKeyDepotManager();
            EncryptionToken etk = manager.getEtk(be.ehealth.technicalconnector.utils.IdentifierType.CBE, new Long(809394427L), "KGSS");

            return etk.getEtk().getEncoded();
        }

        /**
         * Helper method for GetNewKey and GetKey. Returns the ETK of the client application
         *
         * @return the ETK
         * @throws TechnicalConnectorException when a exception occurs
         */
        private byte[] getSystemEtk()
        {
            // The values to use in the ETK Request
            string applicationName = getSessionProps().getProperty("test.myEtk.app");
            string type = getSessionProps().getProperty("test.myEtk.type");
            string value = getSessionProps().getProperty("test.myEtk.value");

            KeyDepotManager manager = KeyDepotManagerFactory.getKeyDepotManager();
            // return the Etk
            EncryptionToken etk = manager.getEtk(be.ehealth.technicalconnector.utils.IdentifierType.lookup(type,null,be.ehealth.technicalconnector.utils.IdentifierType.ETKDEPOT), new Long(Long.parseLong(value)), applicationName);

            return etk.getEtk().getEncoded();
        }

        /**
         * @return
         * @throws TechnicalConnectorException
         * @throws KeyStoreException
         * @throws NoSuchAlgorithmException
         */
        private GetNewKeyResponseContent retrieveResponseForTest()
        {
            /*
             * Set the values to use in this test
             */
            // 1. retrieve the credential. usually an eHealth certificate (retrieved from property file)
            Credential credential = new KeyStoreCredential(getSessionProps().getProperty("test.keystore.location"), getSessionProps().getProperty("test.keystore.alias"), getSessionProps().getProperty("test.keystore.password"));

            // 2a. retrieve the ETK of KGSS (used to seal the request)
            byte[] kgssEtk = getKgssEtk();

            // 2b. retrieve the ETK of your application (inserted into the request, to seal the response)
            byte[] myEtk = getSystemEtk();

            //
            // 3. Use the eHealth Crypto Framework to retrieve the decryption keys
            //
            // load in the keystoremanager to be able to easily work with the keystores
            KeyStoreInfo ksInfo = new KeyStoreInfo(getSessionProps().getProperty("test.keystore.location"), getSessionProps().getProperty("test.keystore.password").ToCharArray(), getSessionProps().getProperty("test.keystore.alias"), getSessionProps().getProperty("test.keystore.password").ToCharArray());
            KeyStoreManager encryptionKeystoreManager = new KeyStoreManager(ksInfo.getKeystorePath(), ksInfo.getKeystorePassword());
            // use the eHealth Crypto Framework to get the decryption keys, it will need the keystore and the password for the private keys
            Map decryptionKeys = KeyManager.getDecryptionKeys(encryptionKeystoreManager.getKeyStore(), ksInfo.getKeystorePassword());

            /*
             * Create request
             */
            GetNewKeyRequestContent content = new GetNewKeyRequestContent();
            // set the etk of the sending application
            content.setETK(myEtk);
            // add an Allowed Reader (retrieved from property file)
            CredentialType ct = new CredentialType();
            ct.setNamespace(getSessionProps().getProperty("test.kgss.ns"));
            ct.setName(getSessionProps().getProperty("test.kgss.name"));
            ct.getValues().add(getSessionProps().getProperty("test.kgss.value"));
            content.getAllowedReaders().add(ct);

            /*
             * 4. Request new key from KGSS Invoke the technical connector framework's KGSS Service's getNewKey operation
             */
            KgssService kgss = ServiceFactory.getKgssService();
            GetNewKeyResponseContent response = kgss.getNewKey(content, credential, decryptionKeys, kgssEtk);
            return response;
        }

        #endregion Methods
    }
}