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

import java.io.Serializable;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.apache.qpid.configuration.ClientProperties;
import org.apache.qpid.transport.ConnectionSettings;
import org.apache.qpid.url.URLHelper;
import org.apache.qpid.url.URLSyntaxException;

public class BrokerDetails implements Serializable
{
    /*
     * Known URL Options
     * @see ConnectionURL
    */
    public static final String OPTIONS_RETRY = "retries";
    public static final String OPTIONS_CONNECT_TIMEOUT = "connecttimeout";
    public static final String OPTIONS_CONNECT_DELAY = "connectdelay";
    public static final String OPTIONS_HEARTBEAT = "heartbeat";
    private static final String OPTIONS_IDLE_TIMEOUT = "idle_timeout";
    public static final String OPTIONS_SASL_MECHS = "sasl_mechs";
    public static final String OPTIONS_SASL_ENCRYPTION = "sasl_encryption";
    public static final String OPTIONS_SSL = "ssl";
    public static final String OPTIONS_TCP_NO_DELAY = "tcp_nodelay";
    public static final String OPTIONS_SASL_PROTOCOL_NAME = "sasl_protocol";
    public static final String OPTIONS_SASL_SERVER_NAME = "sasl_server";
    public static final String OPTIONS_TRUST_STORE = "trust_store";
    public static final String OPTIONS_TRUST_STORE_PASSWORD = "trust_store_password";
    public static final String OPTIONS_KEY_STORE = "key_store";
    public static final String OPTIONS_KEY_STORE_PASSWORD = "key_store_password";
    public static final String OPTIONS_SSL_VERIFY_HOSTNAME = "ssl_verify_hostname";
    public static final String OPTIONS_SSL_CERT_ALIAS = "ssl_cert_alias";
    public static final String OPTIONS_CLIENT_CERT_PRIV_KEY_PATH = "client_cert_priv_key_path";
    public static final String OPTIONS_CLIENT_CERT_PATH = "client_cert_path";
    public static final String OPTIONS_CLIENT_CERT_INTERMEDIARY_CERT_PATH = "client_cert_intermediary_cert_path" ;
    public static final String OPTIONS_TRUSTED_CERTIFICATES_PATH = "trusted_certs_path";

    public static final String OPTIONS_ENCRYPTION_TRUST_STORE = "encryption_trust_store";
    public static final String OPTIONS_ENCRYPTION_TRUST_STORE_PASSWORD = "encryption_trust_store_password";
    public static final String OPTIONS_ENCRYPTION_REMOTE_TRUST_STORE = "encryption_remote_trust_store";
    public static final String OPTIONS_ENCRYPTION_KEY_STORE = "encryption_key_store";
    public static final String OPTIONS_ENCRYPTION_KEY_STORE_PASSWORD = "encryption_key_store_password";

    static final Set<String> PASSWORD_YIELDING_OPTIONS =
            Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
                    OPTIONS_TRUST_STORE_PASSWORD,
                    OPTIONS_KEY_STORE_PASSWORD,
                    OPTIONS_ENCRYPTION_TRUST_STORE_PASSWORD,
                    OPTIONS_ENCRYPTION_KEY_STORE_PASSWORD)));

    public static final int DEFAULT_PORT = 5672;
    public static final String TCP = "tcp";
    public static final String SOCKET = "socket";
    public static final String DEFAULT_TRANSPORT = BrokerDetails.TCP;
    public static final String URL_FORMAT_EXAMPLE =
            "<transport>://<hostname>[:<port Default=\"" + BrokerDetails.DEFAULT_PORT + "\">][?<option>='<value>'[,<option>='<value>']]";
    public static final int DEFAULT_CONNECT_TIMEOUT = 30000;
    public static final boolean USE_SSL_DEFAULT = false;
    // pulled these properties from the new BrokerDetails class in the qpid package
    public static final String PROTOCOL_TCP = "tcp";
    public static final String PROTOCOL_TLS = "tls";
    public static final String VIRTUAL_HOST = "virtualhost";
    public static final String CLIENT_ID = "client_id";
    public static final String USERNAME = "username";
    public static final String PASSWORD = "password";
    private static final long serialVersionUID = 8762219750300869355L;
    private String _host;
    private int _port;
    private String _transport;

    private Map<String, String> _options = new HashMap<String, String>();
    private AMQConnectionURL _connectionUrl;

    public BrokerDetails(BrokerDetails details)
    {
        _host = details.getHost();
        _port = details.getPort();
        _transport = details.getTransport();
        _options = new HashMap<>(details._options);
        _connectionUrl = details._connectionUrl;
    }

    public BrokerDetails(){}
    
    public BrokerDetails(String url) throws URLSyntaxException
    {        
      
        // URL should be of format tcp://host:port?option='value',option='value'
        try
        {
            URI connection = new URI(url);

            String transport = connection.getScheme();

            // Handles some defaults to minimise changes to existing broker URLS e.g. localhost
            if (transport != null)
            {
                //todo this list of valid transports should be enumerated somewhere
                if (!(transport.equalsIgnoreCase(BrokerDetails.TCP) || transport.equalsIgnoreCase(BrokerDetails.SOCKET)))
                {
                    if (transport.equalsIgnoreCase("localhost"))
                    {
                        connection = new URI(DEFAULT_TRANSPORT + "://" + url);
                        transport = connection.getScheme();
                    }
                    else
                    {
                        if (url.charAt(transport.length()) == ':' && url.charAt(transport.length() + 1) != '/')
                        {
                            //Then most likely we have a host:port value
                            connection = new URI(DEFAULT_TRANSPORT + "://" + url);
                            transport = connection.getScheme();
                        }
                        else
                        {
                            throw URLHelper.parseError(0, transport.length(), "Unknown transport", url);
                        }
                    }
                }
                else if (url.indexOf("//") == -1)
                {
                    throw new URLSyntaxException(url, "Missing '//' after the transport In broker URL",transport.length()+1,1);
                }
            }
            else
            {
                //Default the transport
                connection = new URI(DEFAULT_TRANSPORT + "://" + url);
                transport = connection.getScheme();
            }

            if (transport == null)
            {
                throw URLHelper.parseError(-1, "Unknown transport in broker URL:'"
                        + url + "' Format: " + URL_FORMAT_EXAMPLE, "");
            }

            setTransport(transport);

            String host = connection.getHost();

            // Fix for Java 1.5
            if (host == null)
            {
                host = "";
                
                String auth = connection.getAuthority();
                if (auth != null)
                {
                    // contains both host & port myhost:5672                
                    if (auth.contains(":"))
                    {
                        host = auth.substring(0,auth.indexOf(":"));
                    }
                    else
                    {
                        host = auth;
                    }
                }

            }

            setHost(host);

            int port = connection.getPort();

            if (port == -1)
            {
                // Fix for when there is port data but it is not automatically parseable by getPort().
                String auth = connection.getAuthority();

                if (auth != null && auth.contains(":"))
                {
                    int start = auth.indexOf(":") + 1;
                    int end = start;
                    boolean looking = true;
                    boolean found = false;
                    // Throw an URL exception if the port number is not specified
                    if (start == auth.length())
                    {
                        throw URLHelper.parseError(connection.toString().indexOf(auth) + end - 1,
                                connection.toString().indexOf(auth) + end, "Port number must be specified",
                                connection.toString());
                    }
                    //Walk the authority looking for a port value.
                    while (looking)
                    {
                        try
                        {
                            end++;
                            Integer.parseInt(auth.substring(start, end));

                            if (end >= auth.length())
                            {
                                looking = false;
                                found = true;
                            }
                        }
                        catch (NumberFormatException nfe)
                        {
                            looking = false;
                        }

                    }
                    if (found)
                    {
                        setPort(Integer.parseInt(auth.substring(start, end)));
                    }
                    else
                    {
                        throw URLHelper.parseError(connection.toString().indexOf(connection.getAuthority()) + end - 1,
                                             "Illegal character in port number", connection.toString());
                    }

                }
                else
                {
                    setPort(DEFAULT_PORT);
                }
            }
            else
            {
                setPort(port);
            }

            String queryString = connection.getQuery();

            URLHelper.parseOptions(_options, queryString);

            //Fragment is #string (not used)
        }
        catch (URISyntaxException uris)
        {
            if (uris instanceof URLSyntaxException)
            {
                throw(URLSyntaxException) uris;
            }

            throw URLHelper.parseError(uris.getIndex(), uris.getReason(), uris.getInput());
        }
    }

    public BrokerDetails(String host, int port)
    {
        _host = host;
        _port = port;
    }

    public String getHost()
    {
        return _host;
    }

    public void setHost(String _host)
    {
        this._host = _host;
    }

    public int getPort()
    {
        return _port;
    }

    public void setPort(int _port)
    {
        this._port = _port;
    }

    public String getTransport()
    {
        return _transport;
    }

    public void setTransport(String _transport)
    {
        this._transport = _transport;
    }


    public String getProperty(String key)
    {
        String value = _options.get(key);
        if(value == null && _connectionUrl != null)
        {
            value = _connectionUrl.getOption(key);
        }
        return value;
    }

    public void setProperty(String key, String value)
    {
        _options.put(key, value);
    }

    private int lookupConnectTimeout()
    {
        if (_options.containsKey(OPTIONS_CONNECT_TIMEOUT))
        {
            try
            {
                return Integer.parseInt(_options.get(OPTIONS_CONNECT_TIMEOUT));
            }
            catch (NumberFormatException nfe)
            {
                //Do nothing as we will use the default below.
            }
        }

        return BrokerDetails.DEFAULT_CONNECT_TIMEOUT;
    }
    
    public boolean getBooleanProperty(String propName)
    {
        return getBooleanProperty(propName, false);
    }
    
    public boolean getBooleanProperty(String propName, boolean defaultValue)
    {
    	if (_options.containsKey(propName))
    	{
            if (_options.get(propName).equalsIgnoreCase("false"))
            {
                return false;
            }
            else if (_options.get(propName).equalsIgnoreCase("true"))
            {
                return true;
            }
            else
            {
               return defaultValue;
            }
    	}
    	else
    	{
    		return defaultValue;
    	}
    }    

    private int getIntegerProperty(String key)
    {
        String stringValue = getProperty(key);
        try
        {
            return Integer.parseInt(stringValue);
        }
        catch (NumberFormatException e)
        {
            throw new IllegalArgumentException("Cannot parse key " + key + " with value '" + stringValue + "' as integer.", e);
        }
    }

    public String toString()
    {
        StringBuffer sb = new StringBuffer();

        sb.append(_transport);
        sb.append("://");
        sb.append(_host);
        sb.append(':');
        sb.append(_port);

        sb.append(printOptionsURL());

        return sb.toString();
    }

    public boolean equals(Object o)
    {
        if (this == o)
        {
            return true;
        }

        if (o == null || getClass() != o.getClass())
        {
            return false;
        }

        BrokerDetails bd = (BrokerDetails) o;

        return _host.toLowerCase().equals(bd.getHost() == null ? null : bd.getHost().toLowerCase()) &&
               (_port == bd.getPort()) &&
               _transport.toLowerCase().equals(bd.getTransport() == null ? null : bd.getTransport().toLowerCase());
        //TODO do we need to compare all the options as well?
    }

    @Override
    public int hashCode()
    {
        int result = _host != null ? _host.toLowerCase().hashCode() : 0;
        result = 31 * result + _port;
        result = 31 * result + (_transport != null ? _transport.toLowerCase().hashCode() : 0);
        return result;
    }

    private String printOptionsURL()
    {
        return URLHelper.printOptions(_options, PASSWORD_YIELDING_OPTIONS);
    }

    public static String checkTransport(String broker)
    {
        if ((!broker.contains("://")))
        {
            return "tcp://" + broker;
        }
        else
        {
            return broker;
        }
    }

    public ConnectionSettings buildConnectionSettings()
    {
        ConnectionSettings conSettings = new ConnectionSettings();

        conSettings.setHost(getHost());
        conSettings.setPort(getPort());
        conSettings.setTransport(getTransport());

        // ------------ sasl options ---------------
        if (getProperty(BrokerDetails.OPTIONS_SASL_MECHS) != null)
        {
            conSettings.setSaslMechs(
                    getProperty(BrokerDetails.OPTIONS_SASL_MECHS));
        }

        // Sun SASL Kerberos client uses the
        // protocol + servername as the service key.

        if (getProperty(BrokerDetails.OPTIONS_SASL_PROTOCOL_NAME) != null)
        {
            conSettings.setSaslProtocol(
                    getProperty(BrokerDetails.OPTIONS_SASL_PROTOCOL_NAME));
        }


        if (getProperty(BrokerDetails.OPTIONS_SASL_SERVER_NAME) != null)
        {
            conSettings.setSaslServerName(
                    getProperty(BrokerDetails.OPTIONS_SASL_SERVER_NAME));
        }

        conSettings.setUseSASLEncryption(
                getBooleanProperty(BrokerDetails.OPTIONS_SASL_ENCRYPTION));

        // ------------- ssl options ---------------------
        conSettings.setUseSSL(getBooleanProperty(BrokerDetails.OPTIONS_SSL));

        if (getProperty(BrokerDetails.OPTIONS_TRUST_STORE) != null)
        {
            conSettings.setTrustStorePath(
                    getProperty(BrokerDetails.OPTIONS_TRUST_STORE));
        }

        if (getProperty(BrokerDetails.OPTIONS_TRUST_STORE_PASSWORD) != null)
        {
            conSettings.setTrustStorePassword(
                    getProperty(BrokerDetails.OPTIONS_TRUST_STORE_PASSWORD));
        }

        if (getProperty(BrokerDetails.OPTIONS_KEY_STORE) != null)
        {
            conSettings.setKeyStorePath(
                    getProperty(BrokerDetails.OPTIONS_KEY_STORE));
        }

        if (getProperty(BrokerDetails.OPTIONS_KEY_STORE_PASSWORD) != null)
        {
            conSettings.setKeyStorePassword(
                    getProperty(BrokerDetails.OPTIONS_KEY_STORE_PASSWORD));
        }

        if (getProperty(BrokerDetails.OPTIONS_SSL_CERT_ALIAS) != null)
        {
            conSettings.setCertAlias(
                    getProperty(BrokerDetails.OPTIONS_SSL_CERT_ALIAS));
        }

        if (getProperty(BrokerDetails.OPTIONS_CLIENT_CERT_PRIV_KEY_PATH) != null)
        {
            conSettings.setClientCertificatePrivateKeyPath(
                    getProperty(BrokerDetails.OPTIONS_CLIENT_CERT_PRIV_KEY_PATH));
        }

        if (getProperty(BrokerDetails.OPTIONS_CLIENT_CERT_PATH) != null)
        {
            conSettings.setClientCertificatePath(
                    getProperty(BrokerDetails.OPTIONS_CLIENT_CERT_PATH));
        }

        if (getProperty(BrokerDetails.OPTIONS_CLIENT_CERT_INTERMEDIARY_CERT_PATH) != null)
        {
            conSettings.setClientCertificateIntermediateCertsPath(
                    getProperty(BrokerDetails.OPTIONS_CLIENT_CERT_INTERMEDIARY_CERT_PATH));
        }

        if (getProperty(BrokerDetails.OPTIONS_TRUSTED_CERTIFICATES_PATH) != null)
        {
            conSettings.setTrustedCertificatesFile(
                    getProperty(BrokerDetails.OPTIONS_TRUSTED_CERTIFICATES_PATH));
        }
        // ----------------------------

        boolean defaultSSLVerifyHostName = Boolean.parseBoolean(
                System.getProperty(ClientProperties.CONNECTION_OPTION_SSL_VERIFY_HOST_NAME,
                    String.valueOf(ClientProperties.DEFAULT_CONNECTION_OPTION_SSL_VERIFY_HOST_NAME)));
        conSettings.setVerifyHostname(getBooleanProperty(BrokerDetails.OPTIONS_SSL_VERIFY_HOSTNAME, defaultSSLVerifyHostName ));

        // ----------------------------

        if (getProperty(BrokerDetails.OPTIONS_ENCRYPTION_KEY_STORE) != null)
        {
            conSettings.setEncryptionKeyStorePath(
                    getProperty(BrokerDetails.OPTIONS_ENCRYPTION_KEY_STORE));
        }

        if (getProperty(BrokerDetails.OPTIONS_ENCRYPTION_KEY_STORE_PASSWORD) != null)
        {
            conSettings.setEncryptionKeyStorePassword(
                    getProperty(BrokerDetails.OPTIONS_ENCRYPTION_KEY_STORE_PASSWORD));
        }


        if (getProperty(BrokerDetails.OPTIONS_ENCRYPTION_TRUST_STORE) != null)
        {
            conSettings.setEncryptionTrustStorePath(
                    getProperty(BrokerDetails.OPTIONS_ENCRYPTION_TRUST_STORE));
        }

        if (getProperty(BrokerDetails.OPTIONS_ENCRYPTION_TRUST_STORE_PASSWORD) != null)
        {
            conSettings.setEncryptionKeyStorePassword(
                    getProperty(BrokerDetails.OPTIONS_ENCRYPTION_TRUST_STORE_PASSWORD));
        }


        if (getProperty(BrokerDetails.OPTIONS_ENCRYPTION_REMOTE_TRUST_STORE) != null)
        {
            conSettings.setEncryptionRemoteTrustStoreName(
                    getProperty(BrokerDetails.OPTIONS_ENCRYPTION_REMOTE_TRUST_STORE));
        }

        // ----------------------------

        if (getProperty(BrokerDetails.OPTIONS_TCP_NO_DELAY) != null)
        {
            conSettings.setTcpNodelay(
                    getBooleanProperty(BrokerDetails.OPTIONS_TCP_NO_DELAY,true));
        }

        conSettings.setConnectTimeout(lookupConnectTimeout());

        if (getProperty(BrokerDetails.OPTIONS_HEARTBEAT) != null)
        {
            conSettings.setHeartbeatInterval(getIntegerProperty(BrokerDetails.OPTIONS_HEARTBEAT));
        }
        else if (getProperty(BrokerDetails.OPTIONS_IDLE_TIMEOUT) != null)
        {
            conSettings.setHeartbeatInterval(getIntegerProperty(BrokerDetails.OPTIONS_IDLE_TIMEOUT) / 1000);
        }

        return conSettings;
    }

    public void setConnectionUrl(final AMQConnectionURL connectionUrl)
    {
        _connectionUrl = connectionUrl;
    }
}
