/*
 *
 * 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.systests.jms_1_1.extensions;

import java.io.Closeable;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.jms.Connection;
import javax.jms.JMSException;
import javax.jms.Session;
import javax.naming.NamingException;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import org.apache.qpid.server.model.AuthenticationProvider;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.Port;
import org.apache.qpid.server.model.User;
import org.apache.qpid.server.security.FileKeyStore;
import org.apache.qpid.server.security.FileTrustStore;
import org.apache.qpid.server.security.auth.manager.ExternalAuthenticationManager;
import org.apache.qpid.systests.AmqpManagementFacade;
import org.apache.qpid.systests.ConnectionBuilder;

public class BrokerManagementHelper implements Closeable
{
    private final ConnectionBuilder _connectionBuilder;
    private final AmqpManagementFacade _managementFacade;
    private Connection _connection;

    public BrokerManagementHelper(final ConnectionBuilder connectionBuilder,
                                  final AmqpManagementFacade managementFacade)
    {
        _connectionBuilder = connectionBuilder;
        _managementFacade = managementFacade;
    }

    public BrokerManagementHelper openManagementConnection() throws JMSException, NamingException
    {
        _connection = _connectionBuilder.setVirtualHost("$management").build();
        _connection.start();
        return this;
    }

    public BrokerManagementHelper createKeyStore(final String keyStoreName,
                                                 final String keyStoreLocation,
                                                 final String keyStorePassword) throws JMSException
    {
        final Map<String, Object> keyStoreAttributes = new HashMap<>();
        keyStoreAttributes.put("storeUrl", keyStoreLocation);
        keyStoreAttributes.put("password", keyStorePassword);
        keyStoreAttributes.put("keyStoreType", java.security.KeyStore.getDefaultType());
        return createEntity(keyStoreName, FileKeyStore.class.getName(), keyStoreAttributes);
    }

    public BrokerManagementHelper createTrustStore(final String trustStoreName,
                                                   final String trustStoreLocation,
                                                   final String trustStorePassword) throws JMSException
    {
        final Map<String, Object> trustStoreAttributes = new HashMap<>();
        trustStoreAttributes.put("storeUrl", trustStoreLocation);
        trustStoreAttributes.put("password", trustStorePassword);
        trustStoreAttributes.put("trustStoreType", java.security.KeyStore.getDefaultType());
        return createEntity(trustStoreName, FileTrustStore.class.getName(), trustStoreAttributes);
    }

    public BrokerManagementHelper createAmqpTlsPort(final String portName,
                                                    final String authenticationProvider,
                                                    final String keyStoreName,
                                                    final boolean plainAndSsl,
                                                    final boolean needClientAuth,
                                                    final boolean wantClientAuth,
                                                    final String... trustStoreName) throws JMSException
    {
        try
        {
            final Map<String, Object> sslPortAttributes = new HashMap<>();
            sslPortAttributes.put(Port.TRANSPORTS, plainAndSsl ? "[\"SSL\",\"TCP\"]" : "[\"SSL\"]");
            sslPortAttributes.put(Port.PORT, 0);
            sslPortAttributes.put(Port.AUTHENTICATION_PROVIDER, authenticationProvider);
            sslPortAttributes.put(Port.NEED_CLIENT_AUTH, needClientAuth);
            sslPortAttributes.put(Port.WANT_CLIENT_AUTH, wantClientAuth);
            sslPortAttributes.put(Port.NAME, portName);
            sslPortAttributes.put(Port.KEY_STORE, keyStoreName);
            sslPortAttributes.put(Port.TRUST_STORES, new ObjectMapper().writeValueAsString(trustStoreName));
            createEntity(portName, "org.apache.qpid.AmqpPort", sslPortAttributes);
        }
        catch (JsonProcessingException e)
        {
            throw new RuntimeException("Unexpected json processing exception", e);
        }

        return this;
    }

    public BrokerManagementHelper createExternalAuthenticationProvider(String providerName, boolean useFullDN)
            throws JMSException
    {
        final Map<String, Object> providerAttributes = new HashMap<>();
        providerAttributes.put("qpid-type", ExternalAuthenticationManager.PROVIDER_TYPE);
        providerAttributes.put(ExternalAuthenticationManager.ATTRIBUTE_USE_FULL_DN, useFullDN);
        return createEntity(providerName,
                            AuthenticationProvider.class.getName(),
                            providerAttributes);
    }


    public BrokerManagementHelper createAuthenticationProvider(final String providerName, final String providerType)
            throws JMSException
    {
        return createEntity(providerName,
                            AuthenticationProvider.class.getName(),
                            Collections.singletonMap("qpid-type", providerType));
    }

    public BrokerManagementHelper createUser(final String providerName,
                                             final String userName,
                                             final String userPassword)
            throws JMSException
    {
        final Map<String, Object> userAttributes = new HashMap<>();
        userAttributes.put("qpid-type", "managed");
        userAttributes.put(User.PASSWORD, userPassword);
        userAttributes.put("object-path", providerName);
        return createEntity(userName, User.class.getName(), userAttributes);
    }


    public BrokerManagementHelper createEntity(final String name,
                                               final String type,
                                               final Map<String, Object> attributes) throws JMSException
    {
        final Session session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        try
        {

            _managementFacade.createEntityAndAssertResponse(name, type, attributes, session);
        }
        finally
        {
            session.close();
        }
        return this;
    }

    public int getAmqpBoundPort(final String portName) throws JMSException
    {
        return (int) getEffectiveAttribute(portName, "org.apache.qpid.AmqpPort", "boundPort");
    }

    public Object getEffectiveAttribute(final String name, final String type, String attributeName) throws JMSException
    {
        final Map<String, Object> effectiveAttributes = getEffectiveAttributes(name, type);
        if (effectiveAttributes.containsKey(attributeName))
        {
            return effectiveAttributes.get(attributeName);
        }
        throw new RuntimeException(String.format("Attribute '%s' is not found", attributeName));
    }

    public Map<String, Object> getEffectiveAttributes(final String name, final String type) throws JMSException
    {
        final Session session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        try
        {
            return _managementFacade.readEntityUsingAmqpManagement(session, type, name, false);
        }
        finally
        {
            session.close();
        }
    }

    protected List<Map<String, Object>> queryEntitiesUsingAmqpManagement(final String type)
            throws JMSException
    {
        Session session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        try
        {
            return _managementFacade.managementQueryObjects(session, type);
        }
        finally
        {
            session.close();
        }
    }

    public String getConnectionPrincipalByClientId(String portName, String clientId) throws JMSException
    {
        final List<Map<String, Object>> connections = queryEntitiesUsingAmqpManagement("org.apache.qpid.Connection");
        for (final Map<String, Object> connection : connections)
        {
            final String name = String.valueOf(connection.get(ConfiguredObject.NAME));

            final Map<String, Object> attributes =
                    getEffectiveAttributes(portName + "/" + name, "org.apache.qpid.Connection");
            if (attributes.get(org.apache.qpid.server.model.Connection.CLIENT_ID).equals(clientId))
            {
                return String.valueOf(attributes.get(org.apache.qpid.server.model.Connection.PRINCIPAL));
            }
        }
        return null;
    }


    public void close()
    {
        if (_connection != null)
        {
            try
            {
                _connection.close();
            }
            catch (JMSException e)
            {
                throw new RuntimeException("Failure to close JMS connection", e);
            }
        }
    }

    public String getAuthenticationProviderNameForAmqpPort(final int brokerPort)
            throws JMSException
    {
        String authenticationProvider = null;
        Session session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        try
        {
            List<Map<String, Object>> ports =
                    _managementFacade.managementQueryObjects(session, "org.apache.qpid.AmqpPort");
            for (Map<String, Object> port : ports)
            {
                String name = String.valueOf(port.get(Port.NAME));

                Session s = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
                try
                {
                    Map<String, Object> attributes = _managementFacade.readEntityUsingAmqpManagement(s,
                                                                                                     "org.apache.qpid.AmqpPort",
                                                                                                     name,
                                                                                                     false);
                    if (attributes.get("boundPort").equals(brokerPort))
                    {
                        authenticationProvider = String.valueOf(attributes.get(Port.AUTHENTICATION_PROVIDER));
                        break;
                    }
                }
                finally
                {
                    s.close();
                }
            }
        }
        finally
        {
            session.close();
        }
        return authenticationProvider;
    }
}
