/**
 * $RCSfile$
 * $Revision$
 * $Date$
 *
 * Copyright 2009 Jive Software.
 *
 * All rights reserved. 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.jivesoftware.smack;

import java.io.IOException;
import java.io.PipedReader;
import java.io.PipedWriter;
import java.io.Writer;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

import org.jivesoftware.smack.Connection;
import org.jivesoftware.smack.ConnectionCreationListener;
import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.PacketCollector;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.XMPPError;
import org.jivesoftware.smack.util.StringUtils;

import com.kenai.jbosh.BOSHClient;
import com.kenai.jbosh.BOSHClientConfig;
import com.kenai.jbosh.BOSHClientConnEvent;
import com.kenai.jbosh.BOSHClientConnListener;
import com.kenai.jbosh.BOSHClientRequestListener;
import com.kenai.jbosh.BOSHClientResponseListener;
import com.kenai.jbosh.BOSHException;
import com.kenai.jbosh.BOSHMessageEvent;
import com.kenai.jbosh.BodyQName;
import com.kenai.jbosh.ComposableBody;

/**
 * Creates a connection to a XMPP server via HTTP binding.
 * This is specified in the XEP-0206: XMPP Over BOSH.
 * 
 * @see Connection
 * @author Guenther Niess
 */
public class BOSHConnection extends Connection {

    /**
     * The XMPP Over Bosh namespace.
     */
    public static final String XMPP_BOSH_NS = "urn:xmpp:xbosh";

    /**
     * The BOSH namespace from XEP-0124.
     */
    public static final String BOSH_URI = "http://jabber.org/protocol/httpbind";

    /**
     * The used BOSH client from the jbosh library.
     */
    private BOSHClient client;

    /**
     * Holds the initial configuration used while creating the connection.
     */
    private final BOSHConfiguration config;

    // Some flags which provides some info about the current state.
    private boolean connected = false;
    private boolean authenticated = false;
    private boolean anonymous = false;
    private boolean isFirstInitialization = true;
    private boolean wasAuthenticated = false;
    private boolean done = false;

    /**
     * The Thread environment for sending packet listeners.
     */
    private ExecutorService listenerExecutor;

    // The readerPipe and consumer thread are used for the debugger.
    private PipedWriter readerPipe;
    private Thread readerConsumer;

    /**
     * The BOSH equivalent of the stream ID which is used for DIGEST authentication.
     */
    protected String authID = null;

    /**
     * The session ID for the BOSH session with the connection manager.
     */
    protected String sessionID = null;

    /**
     * The full JID of the authenticated user.
     */
    private String user = null;

    /**
     * The roster maybe also called buddy list holds the list of the users contacts.
     */
    private Roster roster = null;


    /**
     * Create a HTTP Binding connection to a XMPP server.
     * 
     * @param https true if you want to use SSL
     *             (e.g. false for http://domain.lt:7070/http-bind).
     * @param host the hostname or IP address of the connection manager
     *             (e.g. domain.lt for http://domain.lt:7070/http-bind).
     * @param port the port of the connection manager
     *             (e.g. 7070 for http://domain.lt:7070/http-bind).
     * @param filePath the file which is described by the URL
     *             (e.g. /http-bind for http://domain.lt:7070/http-bind).
     * @param xmppDomain the XMPP service name
     *             (e.g. domain.lt for the user alice@domain.lt)
     */
    public BOSHConnection(boolean https, String host, int port, String filePath, String xmppDomain) {
        super(new BOSHConfiguration(https, host, port, filePath, xmppDomain));
        this.config = (BOSHConfiguration) getConfiguration();
    }

    /**
     * Create a HTTP Binding connection to a XMPP server.
     * 
     * @param config The configuration which is used for this connection.
     */
    public BOSHConnection(BOSHConfiguration config) {
        super(config);
        this.config = config;
    }

    public void connect() throws XMPPException {
        if (connected) {
            throw new IllegalStateException("Already connected to a server.");
        }
        done = false;
        try {
            // Ensure a clean starting state
            if (client != null) {
                client.close();
                client = null;
            }
            saslAuthentication.init();
            sessionID = null;
            authID = null;

            // Initialize BOSH client
            BOSHClientConfig.Builder cfgBuilder = BOSHClientConfig.Builder
                    .create(config.getURI(), config.getServiceName());
            if (config.isProxyEnabled()) {
                cfgBuilder.setProxy(config.getProxyAddress(), config.getProxyPort());
            }
            client = BOSHClient.create(cfgBuilder.build());

            // Create an executor to deliver incoming packets to listeners.
            // We'll use a single thread with an unbounded queue.
            listenerExecutor = Executors
                    .newSingleThreadExecutor(new ThreadFactory() {
                        public Thread newThread(Runnable runnable) {
                            Thread thread = new Thread(runnable,
                                    "Smack Listener Processor ("
                                            + connectionCounterValue + ")");
                            thread.setDaemon(true);
                            return thread;
                        }
                    });
            client.addBOSHClientConnListener(new BOSHConnectionListener(this));
            client.addBOSHClientResponseListener(new BOSHPacketReader(this));

            // Initialize the debugger
            if (config.isDebuggerEnabled()) {
                initDebugger();
                if (isFirstInitialization) {
                    if (debugger.getReaderListener() != null) {
                        addPacketListener(debugger.getReaderListener(), null);
                    }
                    if (debugger.getWriterListener() != null) {
                        addPacketSendingListener(debugger.getWriterListener(), null);
                    }
                }
            }

            // Send the session creation request
            client.send(ComposableBody.builder()
                    .setNamespaceDefinition("xmpp", XMPP_BOSH_NS)
                    .setAttribute(BodyQName.createWithPrefix(XMPP_BOSH_NS, "version", "xmpp"), "1.0")
                    .build());
        } catch (Exception e) {
            throw new XMPPException("Can't connect to " + getServiceName(), e);
        }

        // Wait for the response from the server
        synchronized (this) {
            long endTime = System.currentTimeMillis() +
                           SmackConfiguration.getPacketReplyTimeout() * 6;
            while ((!connected) && (System.currentTimeMillis() < endTime)) {
                try {
                    wait(Math.abs(endTime - System.currentTimeMillis()));
                }
                catch (InterruptedException e) {}
            }
        }

        // If there is no feedback, throw an remote server timeout error
        if (!connected && !done) {
            done = true;
            String errorMessage = "Timeout reached for the connection to " 
                    + getHost() + ":" + getPort() + ".";
            throw new XMPPException(
                    errorMessage,
                    new XMPPError(XMPPError.Condition.remote_server_timeout, errorMessage));
        }
    }

    public String getConnectionID() {
        if (!connected) {
            return null;
        } else if (authID != null) {
            return authID;
        } else {
            return sessionID;
        }
    }

    public Roster getRoster() {
        if (roster == null) {
            return null;
        }
        if (!config.isRosterLoadedAtLogin()) {
            roster.reload();
        }
        // If this is the first time the user has asked for the roster after calling
        // login, we want to wait for the server to send back the user's roster.
        // This behavior shields API users from having to worry about the fact that
        // roster operations are asynchronous, although they'll still have to listen
        // for changes to the roster. Note: because of this waiting logic, internal
        // Smack code should be wary about calling the getRoster method, and may
        // need to access the roster object directly.
        if (!roster.rosterInitialized) {
            try {
                synchronized (roster) {
                    long waitTime = SmackConfiguration.getPacketReplyTimeout();
                    long start = System.currentTimeMillis();
                    while (!roster.rosterInitialized) {
                        if (waitTime <= 0) {
                            break;
                        }
                        roster.wait(waitTime);
                        long now = System.currentTimeMillis();
                        waitTime -= now - start;
                        start = now;
                    }
                }
            } catch (InterruptedException ie) {
                // Ignore.
            }
        }
        return roster;
    }

    public String getUser() {
        return user;
    }

    public boolean isAnonymous() {
        return anonymous;
    }

    public boolean isAuthenticated() {
        return authenticated;
    }

    public boolean isConnected() {
        return connected;
    }

    public boolean isSecureConnection() {
        // TODO: Implement SSL usage
        return false;
    }

    public boolean isUsingCompression() {
        // TODO: Implement compression
        return false;
    }

    public void login(String username, String password, String resource)
            throws XMPPException {
        if (!isConnected()) {
            throw new IllegalStateException("Not connected to server.");
        }
        if (authenticated) {
            throw new IllegalStateException("Already logged in to server.");
        }
        // Do partial version of nameprep on the username.
        username = username.toLowerCase().trim();

        String response;
        if (config.isSASLAuthenticationEnabled()
                && saslAuthentication.hasNonAnonymousAuthentication()) {
            // Authenticate using SASL
            if (password != null) {
                response = saslAuthentication.authenticate(username, password, resource);
            } else {
                response = saslAuthentication.authenticate(username, resource, config.getCallbackHandler());
            }
        } else {
            // Authenticate using Non-SASL
            response = new NonSASLAuthentication(this).authenticate(username, password, resource);
        }

        // Set the user.
        if (response != null) {
            this.user = response;
            // Update the serviceName with the one returned by the server
            config.setServiceName(StringUtils.parseServer(response));
        } else {
            this.user = username + "@" + getServiceName();
            if (resource != null) {
                this.user += "/" + resource;
            }
        }

        // Create the roster if it is not a reconnection.
        if (this.roster == null) {
            if (this.rosterStorage == null) {
                this.roster = new Roster(this);
            } else {
                this.roster = new Roster(this, rosterStorage);
            }
        }

        // Set presence to online.
        if (config.isSendPresence()) {
            sendPacket(new Presence(Presence.Type.available));
        }

        // Indicate that we're now authenticated.
        authenticated = true;
        anonymous = false;

        if (config.isRosterLoadedAtLogin()) {
            this.roster.reload();
        }
        // Stores the autentication for future reconnection
        config.setLoginInfo(username, password, resource);

        // If debugging is enabled, change the the debug window title to include
        // the
        // name we are now logged-in as.l
        if (config.isDebuggerEnabled() && debugger != null) {
            debugger.userHasLogged(user);
        }
    }

    public void loginAnonymously() throws XMPPException {
    	if (!isConnected()) {
            throw new IllegalStateException("Not connected to server.");
        }
        if (authenticated) {
            throw new IllegalStateException("Already logged in to server.");
        }

        String response;
        if (config.isSASLAuthenticationEnabled() &&
                saslAuthentication.hasAnonymousAuthentication()) {
            response = saslAuthentication.authenticateAnonymously();
        }
        else {
            // Authenticate using Non-SASL
            response = new NonSASLAuthentication(this).authenticateAnonymously();
        }

        // Set the user value.
        this.user = response;
        // Update the serviceName with the one returned by the server
        config.setServiceName(StringUtils.parseServer(response));

        // Anonymous users can't have a roster.
        roster = null;

        // Set presence to online.
        if (config.isSendPresence()) {
            sendPacket(new Presence(Presence.Type.available));
        }

        // Indicate that we're now authenticated.
        authenticated = true;
        anonymous = true;

        // If debugging is enabled, change the the debug window title to include the
        // name we are now logged-in as.
        // If DEBUG_ENABLED was set to true AFTER the connection was created the debugger
        // will be null
        if (config.isDebuggerEnabled() && debugger != null) {
            debugger.userHasLogged(user);
        }
    }

    public void sendPacket(Packet packet) {
        if (!isConnected()) {
            throw new IllegalStateException("Not connected to server.");
        }
        if (packet == null) {
            throw new NullPointerException("Packet is null.");
        }
        if (!done) {
            // Invoke interceptors for the new packet that is about to be sent.
            // Interceptors
            // may modify the content of the packet.
            firePacketInterceptors(packet);

            try {
                send(ComposableBody.builder().setPayloadXML(packet.toXML())
                        .build());
            } catch (BOSHException e) {
                e.printStackTrace();
                return;
            }

            // Process packet writer listeners. Note that we're using the
            // sending
            // thread so it's expected that listeners are fast.
            firePacketSendingListeners(packet);
        }
    }

    public void disconnect(Presence unavailablePresence) {
        if (!connected) {
            return;
        }
        shutdown(unavailablePresence);

        // Cleanup
        if (roster != null) {
            roster.cleanup();
            roster = null;
        }
        sendListeners.clear();
        recvListeners.clear();
        collectors.clear();
        interceptors.clear();

        // Reset the connection flags
        wasAuthenticated = false;
        isFirstInitialization = true;

        // Notify connection listeners of the connection closing if done hasn't already been set.
        for (ConnectionListener listener : getConnectionListeners()) {
            try {
                listener.connectionClosed();
            }
            catch (Exception e) {
                // Catch and print any exception so we can recover
                // from a faulty listener and finish the shutdown process
                e.printStackTrace();
            }
        }
    }

    /**
     * Closes the connection by setting presence to unavailable and closing the 
     * HTTP client. The shutdown logic will be used during a planned disconnection or when
     * dealing with an unexpected disconnection. Unlike {@link #disconnect()} the connection's
     * BOSH packet reader and {@link Roster} will not be removed; thus
     * connection's state is kept.
     *
     * @param unavailablePresence the presence packet to send during shutdown.
     */
    protected void shutdown(Presence unavailablePresence) {
        setWasAuthenticated(authenticated);
        authID = null;
        sessionID = null;
        done = true;
        authenticated = false;
        connected = false;
        isFirstInitialization = false;

        try {
            client.disconnect(ComposableBody.builder()
                    .setNamespaceDefinition("xmpp", XMPP_BOSH_NS)
                    .setPayloadXML(unavailablePresence.toXML())
                    .build());
            // Wait 150 ms for processes to clean-up, then shutdown.
            Thread.sleep(150);
        }
        catch (Exception e) {
            // Ignore.
        }

        // Close down the readers and writers.
        if (readerPipe != null) {
            try {
                readerPipe.close();
            }
            catch (Throwable ignore) { /* ignore */ }
            reader = null;
        }
        if (reader != null) {
            try {
                reader.close();
            }
            catch (Throwable ignore) { /* ignore */ }
            reader = null;
        }
        if (writer != null) {
            try {
                writer.close();
            }
            catch (Throwable ignore) { /* ignore */ }
            writer = null;
        }

        // Shut down the listener executor.
        if (listenerExecutor != null) {
            listenerExecutor.shutdown();
        }
        readerConsumer = null;
    }

    /**
     * Sets whether the connection has already logged in the server.
     *
     * @param wasAuthenticated true if the connection has already been authenticated.
     */
    private void setWasAuthenticated(boolean wasAuthenticated) {
        if (!this.wasAuthenticated) {
            this.wasAuthenticated = wasAuthenticated;
        }
    }

    /**
     * Send a HTTP request to the connection manager with the provided body element.
     * 
     * @param body the body which will be sent.
     */
    protected void send(ComposableBody body) throws BOSHException {
        if (!connected) {
            throw new IllegalStateException("Not connected to a server!");
        }
        if (body == null) {
            throw new NullPointerException("Body mustn't be null!");
        }
        if (sessionID != null) {
            body = body.rebuild().setAttribute(
                    BodyQName.create(BOSH_URI, "sid"), sessionID).build();
        }
        client.send(body);
    }

    /**
     * Processes a packet after it's been fully parsed by looping through the
     * installed packet collectors and listeners and letting them examine the
     * packet to see if they are a match with the filter.
     * 
     * @param packet the packet to process.
     */
    protected void processPacket(Packet packet) {
        if (packet == null) {
            return;
        }

        // Loop through all collectors and notify the appropriate ones.
        for (PacketCollector collector : getPacketCollectors()) {
            collector.processPacket(packet);
        }

        // Deliver the incoming packet to listeners.
        listenerExecutor.submit(new ListenerNotification(packet));
    }

    /**
     * Initialize the SmackDebugger which allows to log and debug XML traffic.
     */
    protected void initDebugger() {
        // TODO: Maybe we want to extend the SmackDebugger for simplification
        //       and a performance boost.

        // Initialize a empty writer which discards all data.
        writer = new Writer() {
                public void write(char[] cbuf, int off, int len) { /* ignore */}
                public void close() { /* ignore */ }
                public void flush() { /* ignore */ }
            };

        // Initialize a pipe for received raw data.
        try {
            readerPipe = new PipedWriter();
            reader = new PipedReader(readerPipe);
        }
        catch (IOException e) {
            // Ignore
        }

        // Call the method from the parent class which initializes the debugger.
        super.initDebugger();

        // Add listeners for the received and sent raw data.
        client.addBOSHClientResponseListener(new BOSHClientResponseListener() {
            public void responseReceived(BOSHMessageEvent event) {
                if (event.getBody() != null) {
                    try {
                        readerPipe.write(event.getBody().toXML());
                        readerPipe.flush();
                    } catch (Exception e) {
                        // Ignore
                    }
                }
            }
        });
        client.addBOSHClientRequestListener(new BOSHClientRequestListener() {
            public void requestSent(BOSHMessageEvent event) {
                if (event.getBody() != null) {
                    try {
                        writer.write(event.getBody().toXML());
                    } catch (Exception e) {
                        // Ignore
                    }
                }
            }
        });

        // Create and start a thread which discards all read data.
        readerConsumer = new Thread() {
            private Thread thread = this;
            private int bufferLength = 1024;

            public void run() {
                try {
                    char[] cbuf = new char[bufferLength];
                    while (readerConsumer == thread && !done) {
                        reader.read(cbuf, 0, bufferLength);
                    }
                } catch (IOException e) {
                    // Ignore
                }
            }
        };
        readerConsumer.setDaemon(true);
        readerConsumer.start();
    }

    /**
     * Sends out a notification that there was an error with the connection
     * and closes the connection.
     *
     * @param e the exception that causes the connection close event.
     */
    protected void notifyConnectionError(Exception e) {
        // Closes the connection temporary. A reconnection is possible
        shutdown(new Presence(Presence.Type.unavailable));
        // Print the stack trace to help catch the problem
        e.printStackTrace();
        // Notify connection listeners of the error.
        for (ConnectionListener listener : getConnectionListeners()) {
            try {
                listener.connectionClosedOnError(e);
            }
            catch (Exception e2) {
                // Catch and print any exception so we can recover
                // from a faulty listener
                e2.printStackTrace();
            }
        }
    }


    /**
     * A listener class which listen for a successfully established connection
     * and connection errors and notifies the BOSHConnection.
     * 
     * @author Guenther Niess
     */
    private class BOSHConnectionListener implements BOSHClientConnListener {

        private final BOSHConnection connection;

        public BOSHConnectionListener(BOSHConnection connection) {
            this.connection = connection;
        }

        /**
         * Notify the BOSHConnection about connection state changes.
         * Process the connection listeners and try to login if the
         * connection was formerly authenticated and is now reconnected.
         */
        public void connectionEvent(BOSHClientConnEvent connEvent) {
            try {
                if (connEvent.isConnected()) {
                    connected = true;
                    if (isFirstInitialization) {
                        isFirstInitialization = false;
                        for (ConnectionCreationListener listener : getConnectionCreationListeners()) {
                            listener.connectionCreated(connection);
                        }
                    }
                    else {
                        try {
                            if (wasAuthenticated) {
                                connection.login(
                                        config.getUsername(),
                                        config.getPassword(),
                                        config.getResource());
                            }
                            for (ConnectionListener listener : getConnectionListeners()) {
                                 listener.reconnectionSuccessful();
                            }
                        }
                        catch (XMPPException e) {
                            for (ConnectionListener listener : getConnectionListeners()) {
                                listener.reconnectionFailed(e);
                           }
                        }
                    }
                }
                else {
                    if (connEvent.isError()) {
                        try {
                            connEvent.getCause();
                        }
                        catch (Exception e) {
                            notifyConnectionError(e);
                        }
                    }
                    connected = false;
                }
            }
            finally {
                synchronized (connection) {
                    connection.notifyAll();
                }
            }
        }
    }

    /**
     * This class notifies all listeners that a packet was received.
     */
    private class ListenerNotification implements Runnable {

        private Packet packet;

        public ListenerNotification(Packet packet) {
            this.packet = packet;
        }

        public void run() {
            for (ListenerWrapper listenerWrapper : recvListeners.values()) {
                listenerWrapper.notifyListener(packet);
            }
        }
    }

	@Override
	public void setRosterStorage(RosterStorage storage)
			throws IllegalStateException {
		if(this.roster!=null){
			throw new IllegalStateException("Roster is already initialized");
		}
		this.rosterStorage = storage;
	}
}
