/*
 * Copyright 2015 Red Hat, Inc. and/or its affiliates
 * and other contributors as indicated by the @author tags.
 *
 * Licensed 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.hawkular.bus.restclient;

import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.Map;

import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.jboss.logging.Logger;

/**
 * You can use this to consume and produce messages on the Hawkular bus.
 *
 * This class is purposefully designed to be simple with very few dependencies (just
 * requires Apache's httpclient and JBoss Logging). Specifically, you do not need
 * any other Hawkular libraries to be able to use this to send messages to the
 * Hawkular bus.
 */
public class RestClient {
    private static final String DEFAULT_URL_PATH = "/hawkular-bus/message/";

    private static final Logger LOG = Logger.getLogger(RestClient.class);

    private final URL endpoint;
    private final DefaultHttpClient httpclient;

    public static enum Type {
        QUEUE, TOPIC
    }

    /**
     * Creates the sender with a default HTTP endpoint of the REST server.
     *
     * @param host
     * @param port if null or -1, no port will be specified in the URL
     * @throws MalformedURLException if one of the parameters consists of invalid URL syntax
     */
    public RestClient(String host, Integer port) throws MalformedURLException {
        this("http", host, port);
    }

    /**
     * Creates the sender with a default endpoint of the REST server.
     *
     * @param protocol http or https
     * @param host
     * @param port if null or -1, no port will be specified in the URL
     * @throws MalformedURLException if one of the parameters consists of invalid URL syntax
     */
    public RestClient(String protocol, String host, Integer port) throws MalformedURLException {
        this(new URL(protocol, host, ((port != null) ? port.intValue() : -1), DEFAULT_URL_PATH));
    }

    /**
     * Endpoint of the REST server, not including the fragment that consists of the queue/topic name.
     * For example: http://host:8080/hawkular-bus/message/
     *
     * If the given URL does not end with a "/", one will be added to it.
     *
     * @param endpoint the REST server endpoint, not including the queue/topic name
     * @throws MalformedURLException if failed to append ending slash to the endpoint URL if one was required
     *                               or if the endpoint cannot be used to refer to queues or topics
     */
    public RestClient(URL endpoint) throws MalformedURLException {
        // make sure the endpoint ends with a "/" since we later will append the queue/topic name to it
        if (endpoint.toString().endsWith("/")){
            this.endpoint = endpoint;
        } else {
            this.endpoint = appendToURL(endpoint, "/");
        }

        // Make sure this endpoint URL is a valid bus endpoint - see if it can be converted to topic or queue URLs.
        // These will throw exceptions if the endpoint URL cannot be used for queues or topics.
        getEndpointForType(Type.QUEUE, "Test");
        getEndpointForType(Type.TOPIC, "Test");

        this.httpclient = new DefaultHttpClient();

        LOG.debugf("Created Hawkular Bus REST client for endpoint [%s]", this.endpoint);
    }

    /**
     * @return the REST endpoint not inluding the fragment that consists of the queue/topic name.
     */
    public URL getEndpoint() {
        return this.endpoint;
    }

    /**
     * Sends a message to the REST endpoint in order to put a message on the given topic.
     *
     * @param name name of the topic
     * @param jsonPayload the actual message (as a JSON string) to put on the bus
     * @param headers any headers to send with the message (can be null or empty)
     * @throws Exception
     */
    public void postTopicMessage(String name, String jsonPayload, Map<String, String> headers) throws Exception {
        postMessage(Type.TOPIC, name, jsonPayload, headers);
    }

    /**
     * Sends a message to the REST endpoint in order to put a message on the given queue.
     *
     * @param name name of the queue
     * @param jsonPayload the actual message (as a JSON string) to put on the bus
     * @param headers any headers to send with the message (can be null or empty)
     * @throws Exception
     */
    public void postQueueMessage(String name, String jsonPayload, Map<String, String> headers) throws Exception {
        postMessage(Type.QUEUE, name, jsonPayload, headers);
    }

    protected void postMessage(Type type, String name, String jsonPayload, Map<String, String> headers)
            throws Exception {
        URL messageUrl = getEndpointForType(type, name);
        sendPost(messageUrl.toURI(), jsonPayload, headers);
    }

    protected void sendPost(URI uri, String jsonPayload, Map<String, String> headers) throws Exception {
        LOG.tracef("Posting message to bus. uri=[%s], json=[%s], headers[%s]", uri, jsonPayload, headers);

        HttpPost request = null;
        try {
            request = new HttpPost(uri);
            if (headers != null) {
                for (Map.Entry<String, String> entry : headers.entrySet()) {
                    request.setHeader(entry.getKey(), entry.getValue());
                }
            }
            request.setEntity(new StringEntity(jsonPayload, ContentType.APPLICATION_JSON));
            HttpResponse httpResponse = httpclient.execute(request);
            StatusLine statusLine = httpResponse.getStatusLine();

            if (statusLine.getStatusCode() != 200) {
                throw new Exception("HTTP post request failed. status-code=[" + statusLine.getStatusCode()
                        + "], reason=["
                        + statusLine.getReasonPhrase() + "], url=[" + request.getURI() + "]");
            }
        } catch (Exception e) {
            LOG.debugf("Failed to post message to bus via URI [%s]. Cause: [%s]", uri.toString(), e.toString());
            throw e;
        } finally {
            if (request != null) {
                request.releaseConnection();
            }
        }
    }

    protected URL getEndpointForType(Type type, String name) throws MalformedURLException {
        switch (type) {
            case QUEUE:
                return appendToURL(endpoint, name + "?type=queue");
            case TOPIC:
                return appendToURL(endpoint, name + "?type=topic");
            default: {
                throw new RuntimeException("Invalid type - please report this bug");
            }
        }
    }

    protected URL appendToURL(URL url, String appendage) throws MalformedURLException {
        String oldUrlString = url.toString();
        String newUrlString = oldUrlString + appendage;
        return new URL(newUrlString);
    }
}

@@ -4340,33 +4340,38 @@
 *%0A     * @param 
-n
+topicN
 ame name of the 
@@ -4605,33 +4605,38 @@
 cMessage(String 
-n
+topicN
 ame, String json
@@ -4724,17 +4724,22 @@
 .TOPIC, 
-n
+topicN
 ame, jso
@@ -4884,17 +4884,22 @@
  @param 
-n
+queueN
 ame name
@@ -5145,25 +5145,30 @@
 sage(String 
-n
+queueN
 ame, String 
@@ -5260,17 +5260,22 @@
 .QUEUE, 
-n
+queueN
 ame, jso

rename params