/*
 *
 * 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;
    }
}
