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

/***
 * Java TelnetD library (embeddable telnet daemon)
 * Copyright (c) 2000-2005 Dieter Wimberger
 * All rights reserved.
 * <p/>
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 * <p/>
 * Neither the name of the author nor the names of its contributors
 * may be used to endorse or promote products derived from this software
 * without specific prior written permission.
 * <p/>
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 ***/

package org.apache.felix.gogo.jline.telnet;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Class that implements a connection with this telnet daemon.<br>
 * It is derived from java.lang.Thread, which reflects the architecture
 * constraint of one thread per connection. This might seem a waste of
 * resources, but as a matter of fact sharing threads would require a
 * far more complex imlementation, due to the fact that telnet is not a
 * stateless protocol (i.e. alive throughout a session of multiple requests
 * and responses).<br>
 * Each Connection instance is created by the listeners ConnectionManager
 * instance, making it part of a threadgroup and passing in an associated
 * ConnectionData instance, that holds vital information about the connection.
 * Be sure to take a look at their documention.<br>
 * <p/>
 * Once the thread has started and is running, it will get a login
 * shell instance from the ShellManager and run passing its own reference.
 *
 * @author Dieter Wimberger
 * @version 2.0 (16/07/2006)
 * @see ConnectionManager
 * @see ConnectionData
 */
public abstract class Connection
        extends Thread {

    private static final Logger LOG = Logger.getLogger(Connection.class.getName());
    private static int number;            //unique number for a thread in the thread group
    private boolean dead;
    private List<ConnectionListener> listeners;

    //Associations
    private ConnectionData connectionData;    //associated information

    /**
     * Constructs a TelnetConnection by invoking its parent constructor
     * and setting of various members.<br>
     * Subsequently instantiates the whole i/o subsystem, negotiating
     * telnet protocol level options etc.<br>
     *
     * @param tcg ThreadGroup that this instance is running in.
     * @param cd  ConnectionData instance containing all vital information
     *            of this connection.
     * @see ConnectionData
     */
    public Connection(ThreadGroup tcg, ConnectionData cd) {
        super(tcg, ("Connection" + (++number)));

        connectionData = cd;
        //init the connection listeners for events
        //(there should actually be only one or two)
        listeners = new CopyOnWriteArrayList<>();
        dead = false;
    }//constructor

    /**
     * Method overloaded to implement following behaviour:
     * <ol>
     * <li> On first entry, retrieve an instance of the configured
     * login shell from the ShellManager and run it.
     * <li> Handle a shell switch or close down disgracefully when
     * problems (i.e. unhandled unchecked exceptions) occur in the
     * running shell.
     * </ol>
     */
    public void run() {
        try {
            doRun();

        } catch (Exception ex) {
            LOG.log(Level.SEVERE, "run()", ex); //Handle properly
        } finally {
            //call close if not dead already
            if (!dead) {
                close();
            }
        }
        LOG.log(Level.FINE, "run():: Returning from " + this.toString());
    }//run

    protected abstract void doRun() throws Exception;

    protected abstract void doClose() throws Exception;

    /**
     * Method to access the associated connection data.
     *
     * @return ConnectionData associated with the Connection instance.
     * @see ConnectionData
     */
    public ConnectionData getConnectionData() {
        return connectionData;
    }//getConnectionData

    /**
     * Closes the connection and its underlying i/o and network
     * resources.<br>
     */
    public synchronized void close() {
        if (!dead) {
            try {
                //connection dead
                dead = true;
                //close i/o
                doClose();
            } catch (Exception ex) {
                LOG.log(Level.SEVERE, "close()", ex);
                //handle
            }
            try {
                //close socket
                connectionData.getSocket().close();
            } catch (Exception ex) {
                LOG.log(Level.SEVERE, "close()", ex);
                //handle
            }
            try {
                //register closed connection in ConnectionManager
                connectionData.getManager().registerClosedConnection(this);
            } catch (Exception ex) {
                LOG.log(Level.SEVERE, "close()", ex);
                //handle
            }
            try {
                //try to interrupt it
                interrupt();
            } catch (Exception ex) {
                LOG.log(Level.SEVERE, "close()", ex);
                //handle
            }


            LOG.log(Level.FINE, "Closed " + this.toString() + " and inactive.");
        }
    }//close

    /**
     * Returns if a connection has been closed.<br>
     *
     * @return the state of the connection.
     */
    public boolean isActive() {
        return !dead;
    }//isClosed

    /****** Event handling ****************/

    /**
     * Method that registers a ConnectionListener with the
     * Connection instance.
     *
     * @param cl ConnectionListener to be registered.
     * @see ConnectionListener
     */
    public void addConnectionListener(ConnectionListener cl) {
        listeners.add(cl);
    }//addConnectionListener

    /**
     * Method that removes a ConnectionListener from the
     * Connection instance.
     *
     * @param cl ConnectionListener to be removed.
     * @see ConnectionListener
     */
    public void removeConnectionListener(ConnectionListener cl) {
        listeners.remove(cl);
    }//removeConnectionListener


    /**
     * Method called by the io subsystem to pass on a
     * "low-level" event. It will be properly delegated to
     * all registered listeners.
     *
     * @param ce ConnectionEvent to be processed.
     * @see ConnectionEvent
     */
    public void processConnectionEvent(ConnectionEvent ce) {
        for (ConnectionListener cl : listeners) {
            switch (ce.getType()) {
                case CONNECTION_IDLE:
                    cl.connectionIdle(ce);
                    break;
                case CONNECTION_TIMEDOUT:
                    cl.connectionTimedOut(ce);
                    break;
                case CONNECTION_LOGOUTREQUEST:
                    cl.connectionLogoutRequest(ce);
                    break;
                case CONNECTION_BREAK:
                    cl.connectionSentBreak(ce);
                    break;
                case CONNECTION_TERMINAL_GEOMETRY_CHANGED:
                    cl.connectionTerminalGeometryChanged(ce);
            }
        }
    }//processConnectionEvent

}//class Connection
