/*
 * 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 flex.messaging.config;

import flex.messaging.util.StringUtils;

/**
 * The channel configuration is intentionally generic so that
 * other channels can be added in the future. This format also allows
 * server-endpoint specific and client code-generation specific settings
 * to be modified without affecting needing to update the configuration
 * parser.
 */
public class ChannelSettings extends PropertiesSettings {
    protected String id;
    protected boolean remote;
    protected String serverId;
    private String sourceFile;

    protected SecurityConstraint constraint;

    // ENDPOINT
    protected String uri;
    protected int port;
    protected String endpointType;
    protected String clientType;
    protected boolean serverOnly;

    protected String parsedUri;
    protected boolean contextParsed;
    protected String parsedClientUri;
    protected boolean clientContextParsed;

    public ChannelSettings(String id) {
        this.id = id;
    }

    public String getId() {
        return id;
    }

    public boolean isRemote() {
        return remote;
    }

    public void setRemote(boolean value) {
        remote = value;
    }

    public String getServerId() {
        return serverId;
    }

    public void setServerId(String value) {
        serverId = value;
    }

    public String getClientType() {
        return clientType;
    }

    public void setClientType(String type) {
        this.clientType = type;
    }

    public boolean getServerOnly() {
        return serverOnly;
    }

    public void setServerOnly(boolean serverOnly) {
        this.serverOnly = serverOnly;
    }

    String getSourceFile() {
        return sourceFile;
    }

    void setSourceFile(String sourceFile) {
        this.sourceFile = sourceFile;
    }

    /**
     * A return value of 0 denotes no port in channel url.
     *
     * @return the port number for this channel
     * or 0 if channel url does not contain a port number
     */
    public int getPort() {
        return port;
    }

    public String getUri() {
        return uri;
    }

    public void setUri(String uri) {
        this.uri = uri;
        port = parsePort(uri);
        port = (port == -1) ? 0 : port; // Replace -1 with 0.
        contextParsed = false;
        clientContextParsed = false;
    }

    public String getClientParsedUri(String contextPath) {
        if (!clientContextParsed)
            parseClientUri(this, contextPath);

        return parsedClientUri;
    }

    public String getEndpointType() {
        return endpointType;
    }

    public void setEndpointType(String type) {
        this.endpointType = type;
    }

    public SecurityConstraint getConstraint() {
        return constraint;
    }

    public void setConstraint(SecurityConstraint constraint) {
        this.constraint = constraint;
    }

    /**
     * In this client version of the URI parser we're just looking to
     * replace the context root tokens.
     */
    private static void parseClientUri(ChannelSettings cs, String contextPath) {
        if (!cs.clientContextParsed) {
            String channelEndpoint = cs.getUri().trim();

            // either {context-root} or {context.root} is legal
            channelEndpoint = StringUtils.substitute(channelEndpoint, "{context-root}", ConfigurationConstants.CONTEXT_PATH_TOKEN);

            if ((contextPath == null) && (channelEndpoint.indexOf(ConfigurationConstants.CONTEXT_PATH_TOKEN) != -1)) {
                // context root must be specified before it is used
                ConfigurationException e = new ConfigurationException();
                e.setMessage(ConfigurationConstants.UNDEFINED_CONTEXT_ROOT, new Object[]{cs.getId()});
                throw e;
            }

            // simplify the number of combinations to test by ensuring our
            // context path always starts with a slash
            if (contextPath != null && !contextPath.startsWith("/")) {
                contextPath = "/" + contextPath;
            }

            // avoid double-slashes from context root by replacing /{context.root}
            // in a single replacement step
            if (channelEndpoint.indexOf(ConfigurationConstants.SLASH_CONTEXT_PATH_TOKEN) != -1) {
                // but avoid double-slash for /{context.root}/etc when we have
                // the default context root
                if ("/".equals(contextPath) && !ConfigurationConstants.SLASH_CONTEXT_PATH_TOKEN.equals(channelEndpoint))
                    contextPath = "";

                channelEndpoint = StringUtils.substitute(channelEndpoint, ConfigurationConstants.SLASH_CONTEXT_PATH_TOKEN, contextPath);
            }
            // otherwise we have something like {server.name}:{server.port}{context.root}...
            else {
                // but avoid double-slash for {context.root}/etc when we have
                // the default context root
                if ("/".equals(contextPath) && !ConfigurationConstants.CONTEXT_PATH_TOKEN.equals(channelEndpoint))
                    contextPath = "";

                channelEndpoint = StringUtils.substitute(channelEndpoint, ConfigurationConstants.CONTEXT_PATH_TOKEN, contextPath);
            }

            cs.parsedClientUri = channelEndpoint;
            cs.clientContextParsed = true;
        }
    }

    /**
     * Returns the host name in the URL, or an empty <tt>String</tt> if the URL does not contain a host name.
     *
     * @param url The URL to parse for a host name.
     * @return The host name or an empty <tt>String</tt> if the URL does not contain a host name.
     */
    // The reason for this method, rather than just using java.net.URL, is that the Java class
    // doesn't recognize many of our protocol types/schemes (e.g. rtmp, amfsocket, etc.)
    public static String parseHost(String url) {
        int start = url.indexOf(":/");
        if (start == -1)
            return "";

        start = start + 3; // Advance past all of '://' to beginning of host name.
        int end = url.indexOf('/', start);
        String hostnameWithPort = end == -1 ? url.substring(start) : url.substring(start, end);

        // IPv6 hostnames may contain ':' but the full value is wrapped in [] - skip past if necessary.
        int delim = hostnameWithPort.indexOf(']');
        delim = (delim != -1) ? hostnameWithPort.indexOf(':', delim) : hostnameWithPort.indexOf(':');
        if (delim == -1) // No port.
            return hostnameWithPort;
        else
            return hostnameWithPort.substring(0, delim);
    }

    /**
     * Returns the port number specified in the URL, or 0 if the URL
     * does not contain a port number, or -1 if the URL contains a server.port
     * token.
     *
     * @param url The URL to parse for a contained port number.
     * @return the port number in the URL, or 0 if the URL does not
     * contain a port number, or -1 if the URL contains a server.port token.
     */
    // The reason for this method, rather than just using java.net.URL, is that the Java class
    // doesn't recognize many of our protocol types/schemes (e.g. rtmp, amfsocket, etc.)
    public static int parsePort(String url) {
        // rtmp://localhost:2035/foo/bar
        // Find first slash with colon
        int start = url.indexOf(":/");
        if (start == -1)
            return 0;

        // Second slash should be +1, so start 3 after for ://
        start = start + 3;
        int end = url.indexOf('/', start);

        // take everything up until the next slash for servername:port
        String snp = end == -1 ? url.substring(start) : url.substring(start, end);

        // If IPv6 is in use, start looking after the square bracket.
        int delim = snp.indexOf(']');
        delim = (delim > -1) ? snp.indexOf(':', delim) : snp.indexOf(':');
        if (delim == -1)
            return 0;

        int port = 0;
        try {
            int p = Integer.parseInt(snp.substring(delim + 1));
            port = (p > 0) ? p : 0;
        } catch (Throwable t) {
            port = -1; // To denote that the url contained server.port token.
        }
        return port;
    }

    /**
     * Remove protocol, host, port and context-root from a given url.
     * Unlike parseClientUri, this method does not check if the channel
     * setting has been parsed before.
     *
     * @param url Original url.
     * @return Url with protocol, host, port and context-root removed.
     */
    public static String removeTokens(String url) {
        String channelEndpoint = url.toLowerCase().trim();

        // remove protocol and host info
        if (channelEndpoint.startsWith("http://") ||
                channelEndpoint.startsWith("https://") ||
                channelEndpoint.startsWith("rtmp://") ||
                channelEndpoint.startsWith("rtmps://")) {
            int nextSlash = channelEndpoint.indexOf('/', 8);
            // Check to see if there is a 'next slash', and also that the next
            // slash isn't the last character
            if ((nextSlash > 0) && (nextSlash != channelEndpoint.length() - 1))
                channelEndpoint = channelEndpoint.substring(nextSlash);
        }

        // either {context-root} or {context.root} is legal
        channelEndpoint = StringUtils.substitute(channelEndpoint, "{context-root}", ConfigurationConstants.CONTEXT_PATH_TOKEN);

        // Remove context path info
        if (channelEndpoint.startsWith(ConfigurationConstants.CONTEXT_PATH_TOKEN)) {
            channelEndpoint = channelEndpoint.substring(ConfigurationConstants.CONTEXT_PATH_TOKEN.length());
        } else if (channelEndpoint.startsWith(ConfigurationConstants.SLASH_CONTEXT_PATH_TOKEN)) {
            channelEndpoint = channelEndpoint.substring(ConfigurationConstants.SLASH_CONTEXT_PATH_TOKEN.length());
        }

        // We also don't match on trailing slashes
        if (channelEndpoint.endsWith("/")) {
            channelEndpoint = channelEndpoint.substring(0, channelEndpoint.length() - 1);
        }
        return channelEndpoint;
    }
}
