/*
 * 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.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Stack;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Class that takes care for active and queued connection.
 * Housekeeping is done also for connections that were just broken
 * off, or exceeded their timeout. 
 *
 * @author Dieter Wimberger
 * @version 2.0 (16/07/2006)
 */
public abstract class ConnectionManager implements Runnable {

    private static Logger LOG = Logger.getLogger(ConnectionManager.class.getName());
    private final List<Connection> openConnections;
    private Thread thread;
    private ThreadGroup threadGroup; //ThreadGroup all connections run in
    private Stack<Connection> closedConnections;
    private ConnectionFilter connectionFilter; //reference to the connection filter
    private int maxConnections; //maximum allowed connections stored from the properties
    private int warningTimeout; //time to idle warning
    private int disconnectTimeout; //time to idle diconnection
    private int housekeepingInterval; //interval for managing cleanups
    private String loginShell;
    private boolean lineMode = false;
    private boolean stopping = false;

    public ConnectionManager() {
        threadGroup = new ThreadGroup(toString() + "Connections");
        closedConnections = new Stack<>();
        openConnections = Collections.synchronizedList(new ArrayList<>(100));
    }

    public ConnectionManager(int con, int timew, int timedis, int hoke, ConnectionFilter filter, String lsh, boolean lm) {
        this();
        connectionFilter = filter;
        loginShell = lsh;
        lineMode = lm;
        maxConnections = con;
        warningTimeout = timew;
        disconnectTimeout = timedis;
        housekeepingInterval = hoke;
    }//constructor

    /**
     * Gets the active ConnectionFilter instance or
     * returns null if no filter is set.
     *
     * @return the managers ConnectionFilter.
     */
    public ConnectionFilter getConnectionFilter() {
        return connectionFilter;
    }//getConnectionFilter

    /**
     * Set a connection filter for this
     * ConnectionManager instance. The filter is used to handle
     * IP level allow/deny of incoming connections.
     *
     * @param filter ConnectionFilter instance.
     */
    public void setConnectionFilter(ConnectionFilter filter) {
        connectionFilter = filter;
    }//setConnectionFilter

    /**
     * Returns the number of open connections.
     * @return the number of open connections as <tt>int</tt>.
     */
    public int openConnectionCount() {
        return openConnections.size();
    }//openConnectionCount

    /**
     * Returns the {@link Connection} at the given index.
     * @param idx
     * @return
     */
    public Connection getConnection(int idx) {
        synchronized (openConnections) {
            return openConnections.get(idx);
        }
    }//getConnection

    /**
     * Get all {@link Connection} instances with the given
     * <tt>InetAddress</tt>.
     *
     * @return all {@link Connection} instances with the given
     *         <tt>InetAddress</tt>.
     */
    public Connection[] getConnectionsByAdddress(InetAddress addr) {
        ArrayList<Connection> l = new ArrayList<>();
        synchronized (openConnections) {
            for (Connection connection : openConnections) {
                if (connection.getConnectionData().getInetAddress().equals(addr)) {
                    l.add(connection);
                }
            }
        }
        Connection[] conns = new Connection[l.size()];
        return l.toArray(conns);
    }//getConnectionsByAddress

    /**
     * Starts this <tt>ConnectionManager</tt>.
     */
    public void start() {
        thread = new Thread(this);
        thread.start();
    }//start

    /**
     * Stops this <tt>ConnectionManager</tt>.
     */
    public void stop() {
        LOG.log(Level.FINE, "stop()::" + this.toString());
        stopping = true;
        //wait for thread to die
        try {
            if (thread != null) {
                thread.join();
            }
        } catch (InterruptedException iex) {
            LOG.log(Level.SEVERE, "stop()", iex);
        }
        synchronized (openConnections) {
            for (Connection tc : openConnections) {
                try {
                    //maybe write a disgrace to the socket?
                    tc.close();
                } catch (Exception exc) {
                    LOG.log(Level.SEVERE, "stop()", exc);
                }
            }
            openConnections.clear();
        }
        LOG.log(Level.FINE, "stop():: Stopped " + this.toString());
    }//stop

    /**
     * Method that that tries to connect an incoming request.
     * Properly  queueing.
     *
     * @param insock Socket thats representing the incoming connection.
     */
    public void makeConnection(Socket insock) {
        LOG.log(Level.FINE, "makeConnection()::" + insock.toString());
        if (connectionFilter == null || connectionFilter.isAllowed(insock.getInetAddress())) {
            //we create the connection data object at this point to
            //store certain information there.
            ConnectionData newCD = new ConnectionData(insock, this);
            newCD.setLoginShell(loginShell);
            newCD.setLineMode(lineMode);
            if (openConnections.size() < maxConnections) {
                //create a new Connection instance
                Connection con = createConnection(threadGroup, newCD);
                //log the newly created connection
                Object[] args = {openConnections.size() + 1};
                LOG.info(MessageFormat.format("connection #{0,number,integer} made.", args));
                //register it for being managed
                synchronized (openConnections) {
                    openConnections.add(con);
                }
                //start it
                con.start();
            }
        } else {
            LOG.info("makeConnection():: Active Filter blocked incoming connection.");
            try {
                insock.close();
            } catch (IOException ex) {
                //do nothing or log.
            }
        }
    }//makeConnection

    protected abstract Connection createConnection(ThreadGroup threadGroup, ConnectionData newCD);

    /**
     * Periodically does following work:
     * <ul>
     * <li> cleaning up died connections.
     * <li> checking managed connections if they are working properly.
     * <li> checking the open connections.
     * </ul>
     */
    public void run() {
        //housekeep connections
        try {
            do {
                //clean up and close all broken connections
                //cleanupBroken();
                //clean up closed connections
                cleanupClosed();
                //check all active connections
                checkOpenConnections();
                //sleep interval
                Thread.sleep(housekeepingInterval);
            } while (!stopping);

        } catch (Exception e) {
            LOG.log(Level.SEVERE, "run()", e);
        }
        LOG.log(Level.FINE, "run():: Ran out " + this.toString());
    }//run

    /*
    private void cleanupBroken() {
      //cleanup loop
      while (!m_BrokenConnections.isEmpty()) {
        Connection nextOne = (Connection) m_BrokenConnections.pop();
        log.info("cleanupBroken():: Closing broken connection " + nextOne.toString());
        //fire logoff event for shell site cleanup , beware could hog the daemon thread
        nextOne.processConnectionEvent(new ConnectionEvent(nextOne, ConnectionEvent.CONNECTION_BROKEN));
        //close the connection, will be automatically registered as closed
        nextOne.close();
      }
    }//cleanupBroken
    */
    private void cleanupClosed() {
        if (stopping) {
            return;
        }
        //cleanup loop
        while (!closedConnections.isEmpty()) {
            Connection nextOne = closedConnections.pop();
            LOG.info("cleanupClosed():: Removing closed connection " + nextOne.toString());
            synchronized (openConnections) {
                openConnections.remove(nextOne);
            }
        }
    }//cleanupBroken

    private void checkOpenConnections() {
        if (stopping) {
            return;
        }
        //do routine checks on active connections
        synchronized (openConnections) {
            for (Connection conn : openConnections) {
                ConnectionData cd = conn.getConnectionData();
                //check if it is dead and remove it.
                if (!conn.isActive()) {
                    registerClosedConnection(conn);
                    continue;
                }
                /* Timeouts check */
                //first we caculate the inactivity time
                long inactivity = System.currentTimeMillis() - cd.getLastActivity();
                //now we check for warning and disconnection
                if (inactivity > warningTimeout) {
                    //..and for disconnect
                    if (inactivity > (disconnectTimeout + warningTimeout)) {
                        //this connection needs to be disconnected :)
                        LOG.log(Level.FINE, "checkOpenConnections():" + conn.toString() + " exceeded total timeout.");
                        //fire logoff event for shell site cleanup , beware could hog the daemon thread
                        conn.processConnectionEvent(new ConnectionEvent(conn, ConnectionEvent.Type.CONNECTION_TIMEDOUT));
                        //conn.close();
                    } else {
                        //this connection needs to be warned :)
                        if (!cd.isWarned()) {
                            LOG.log(Level.FINE, "checkOpenConnections():" + conn.toString() + " exceeded warning timeout.");
                            cd.setWarned(true);
                            //warning event is fired but beware this could hog the daemon thread!!
                            conn.processConnectionEvent(new ConnectionEvent(conn, ConnectionEvent.Type.CONNECTION_IDLE));
                        }
                    }
                }
            }
            /* end Timeouts check */
        }
    }//checkConnections

    public void registerClosedConnection(Connection con) {
        if (stopping) {
            return;
        }
        if (!closedConnections.contains(con)) {
            LOG.log(Level.FINE, "registerClosedConnection()::" + con.toString());
            closedConnections.push(con);
        }
    }//unregister

    public int getDisconnectTimeout() {
        return disconnectTimeout;
    }

    public void setDisconnectTimeout(int disconnectTimeout) {
        this.disconnectTimeout = disconnectTimeout;
    }

    public int getHousekeepingInterval() {
        return housekeepingInterval;
    }

    public void setHousekeepingInterval(int housekeepingInterval) {
        this.housekeepingInterval = housekeepingInterval;
    }

    public boolean isLineMode() {
        return lineMode;
    }

    public void setLineMode(boolean lineMode) {
        this.lineMode = lineMode;
    }

    public String getLoginShell() {
        return loginShell;
    }

    public void setLoginShell(String loginShell) {
        this.loginShell = loginShell;
    }

    public int getMaxConnections() {
        return maxConnections;
    }

    public void setMaxConnections(int maxConnections) {
        this.maxConnections = maxConnections;
    }

    public int getWarningTimeout() {
        return warningTimeout;
    }

    public void setWarningTimeout(int warningTimeout) {
        this.warningTimeout = warningTimeout;
    }

}//class ConnectionManager
