/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 */
package org.apache.qpid.client.message;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.security.GeneralSecurityException;
import java.security.PrivateKey;
import java.util.Collection;
import java.util.Iterator;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.security.auth.x500.X500Principal;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.qpid.QpidException;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.framing.BasicContentHeaderProperties;

public class Encrypted091MessageFactory extends AbstractJMSMessageFactory
{
    public static final String ENCRYPTED_0_9_1_CONTENT_TYPE = "application/qpid-0-9-1-encrypted";
    private static final Logger LOGGER = LoggerFactory.getLogger(Encrypted091MessageFactory.class);

    private final MessageFactoryRegistry _messageFactoryRegistry;

    public Encrypted091MessageFactory(final MessageFactoryRegistry messageFactoryRegistry)
    {
        _messageFactoryRegistry = messageFactoryRegistry;
    }

    @Override
    protected AbstractJMSMessage createMessage(final AbstractAMQMessageDelegate delegate, final ByteBuffer data)
            throws QpidException
    {
        SecretKeySpec secretKeySpec;
        String algorithm;
        byte[] initVector;
        try
        {


            try
            {
                if (delegate.hasProperty(MessageEncryptionHelper.ENCRYPTION_ALGORITHM_PROPERTY))
                {
                    algorithm = delegate.getProperty(MessageEncryptionHelper.ENCRYPTION_ALGORITHM_PROPERTY).toString();

                    if (delegate.hasProperty(MessageEncryptionHelper.KEY_INIT_VECTOR_PROPERTY))
                    {
                        Object ivObj = delegate.getProperty(MessageEncryptionHelper.KEY_INIT_VECTOR_PROPERTY);
                        if (ivObj instanceof byte[])
                        {
                            initVector = (byte[]) ivObj;
                        }
                        else
                        {
                            throw new QpidException("If the property '"
                                                   + MessageEncryptionHelper.KEY_INIT_VECTOR_PROPERTY
                                                   + "' is present, it must contain a byte array");
                        }
                    }
                    else
                    {
                        initVector = null;
                    }
                    if (delegate.hasProperty(MessageEncryptionHelper.ENCRYPTED_KEYS_PROPERTY))
                    {
                        Object keyInfoObj = delegate.getProperty(MessageEncryptionHelper.ENCRYPTED_KEYS_PROPERTY);
                        if (keyInfoObj instanceof Collection)
                        {
                            secretKeySpec = getContentEncryptionKey((Collection) keyInfoObj,
                                                                    algorithm,
                                                                    _messageFactoryRegistry.getSession());
                        }
                        else
                        {
                            throw new QpidException("An encrypted message must contain the property '"
                                                   + MessageEncryptionHelper.ENCRYPTED_KEYS_PROPERTY
                                                   + "'");
                        }
                    }
                    else
                    {
                        throw new QpidException("An encrypted message must contain the property '"
                                               + MessageEncryptionHelper.ENCRYPTED_KEYS_PROPERTY
                                               + "'");
                    }

                }
                else
                {
                    throw new QpidException("Encrypted message must carry the encryption algorithm in the property '"
                                           + MessageEncryptionHelper.ENCRYPTED_KEYS_PROPERTY
                                           + "'");
                }

                Cipher cipher = Cipher.getInstance(algorithm);
                cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(initVector));
                byte[] encryptedData;
                int offset;
                int length;
                if (data.hasArray())
                {
                    encryptedData = data.array();
                    offset = data.arrayOffset() + data.position();
                    length = data.remaining();
                }
                else
                {
                    encryptedData = new byte[data.remaining()];
                    data.duplicate().get(encryptedData);
                    offset = 0;
                    length = encryptedData.length;
                }
                final byte[] unencryptedBytes = decryptData(cipher, encryptedData, offset, length);

                BasicContentHeaderProperties properties = new BasicContentHeaderProperties();
                int payloadOffset;
                ByteBuffer dataInput = ByteBuffer.wrap(unencryptedBytes);

                payloadOffset = properties.read(dataInput);


                final ByteBuffer unencryptedData =
                        ByteBuffer.wrap(unencryptedBytes, payloadOffset, unencryptedBytes.length - payloadOffset);

                final AbstractAMQMessageDelegate newDelegate =
                        new AMQMessageDelegate_0_8(properties, delegate.getDeliveryTag());
                newDelegate.setJMSDestination(delegate.getJMSDestination());


                final AbstractJMSMessageFactory unencryptedMessageFactory =
                        _messageFactoryRegistry.getMessageFactory(properties.getContentTypeAsString());

                return unencryptedMessageFactory.createMessage(newDelegate, unencryptedData);
            }
            catch (GeneralSecurityException | IOException e)
            {
                throw new QpidException("Could not decode encrypted message", e);
            }
        }
        catch(QpidException e)
        {
            LOGGER.error("Error when attempting to decrypt message " + delegate.getDeliveryTag() + " to address ("+delegate.getJMSDestination()+").  Message will be delivered to the client encrypted", e);
            return _messageFactoryRegistry.getDefaultFactory().createMessage(delegate, data);
        }

    }

    private byte[] decryptData(final Cipher cipher, final byte[] encryptedData, final int offset, final int length)
            throws IOException
    {
        final byte[] unencryptedBytes;
        try (CipherInputStream cipherInputStream = new CipherInputStream(new ByteArrayInputStream(encryptedData,
                                                                                                  offset,
                                                                                                  length), cipher))
        {
            byte[] buf = new byte[512];
            int pos = 0;
            int read;
            while ((read = cipherInputStream.read(buf, pos, buf.length - pos)) != -1)
            {
                pos += read;
                if (pos == buf.length)
                {
                    byte[] tmp = buf;
                    buf = new byte[buf.length + 512];
                    System.arraycopy(tmp, 0, buf, 0, tmp.length);
                }
            }
            unencryptedBytes= new byte[pos];
            System.arraycopy(buf, 0, unencryptedBytes, 0, pos);
        }
        return unencryptedBytes;
    }

    private SecretKeySpec getContentEncryptionKey(final Collection keyInfoObjList,
                                                  final String algorithm,
                                                  final AMQSession<?, ?> session)
            throws QpidException, GeneralSecurityException, IOException
    {

        for(Object keyInfoObject : keyInfoObjList)
        {
            try
            {
                Iterator iter = ((Collection)keyInfoObject).iterator();

                int type = ((Number)iter.next()).intValue();
                switch(type)
                {
                    case 1:
                        String keyEncryptionAlgorithm = (String) iter.next();
                        X500Principal issuer = new X500Principal((String)iter.next());
                        BigInteger serialNumber = new BigInteger((String)iter.next());
                        byte[] encryptedKey = (byte[])iter.next();

                        PrivateKey privateKey = getPrivateKey(session, issuer, serialNumber);
                        if(privateKey != null)
                        {
                            Cipher cipher = Cipher.getInstance(keyEncryptionAlgorithm);
                            cipher.init(Cipher.DECRYPT_MODE, privateKey);
                            byte[] decryptedData = decryptData(cipher, encryptedKey, 0, encryptedKey.length);
                            SecretKeySpec keySpec = new SecretKeySpec(decryptedData, algorithm.split("/")[0]);
                            return keySpec;
                        }
                        break;
                    default:
                        throw new QpidException("Invalid format of 'x-qpid-encrypted-keys' - unknown key info type: " + type);

                }
            }
            catch(ClassCastException e)
            {
                throw new QpidException("Invalid format of 'x-qpid-encrypted-keys'");
            }
        }
        return null;
    }

    private PrivateKey getPrivateKey(final AMQSession<?, ?> session,
                                     final X500Principal issuer,
                                     final BigInteger serialNumber)
            throws GeneralSecurityException, IOException
    {
        return session.getMessageEncryptionHelper().getEncryptionPrivateKey(issuer, serialNumber);
    }

}
