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

#ifndef _LOG4CXX_NET_TELNET_APPENDER_H
#define _LOG4CXX_NET_TELNET_APPENDER_H

#if defined(_MSC_VER)
	#pragma warning ( push )
	#pragma warning ( disable: 4231 4251 4275 4786 )
#endif



#include <log4cxx/appenderskeleton.h>
#include <log4cxx/helpers/socket.h>
#include <log4cxx/helpers/serversocket.h>
#include <thread>
#include <vector>
#include <log4cxx/helpers/charsetencoder.h>

namespace log4cxx
{
namespace helpers
{
class ByteBuffer;
}
namespace net
{
typedef log4cxx::helpers::SocketPtr Connection;
LOG4CXX_LIST_DEF(ConnectionList, Connection);

/**
<p>The TelnetAppender is a log4cxx appender that specializes in
writing to a read-only socket.  The output is provided in a
telnet-friendly way so that a log can be monitored over TCP/IP.
Clients using telnet connect to the socket and receive log data.
This is handy for remote monitoring, especially when monitoring a
servlet.

<p>Here is a list of the available configuration options:

<table border=1>
<tr>
<td align=center><b>Name</b></td>
<td align=center><b>Requirement</b></td>
<td align=center><b>Description</b></td>
<td align=center><b>Sample Value</b></td>
</tr>

<tr>
<td>Port</td>
<td>optional</td>
<td>This parameter determines the port to use for announcing log events.  The default port is 23 (telnet).</td>
<td>5875</td>
</table>
*/
class LOG4CXX_EXPORT TelnetAppender : public AppenderSkeleton
{
		class SocketHandler;
		friend class SocketHandler;
	private:
		static const int DEFAULT_PORT;
		static const int MAX_CONNECTIONS;
		int port;

	public:
		DECLARE_LOG4CXX_OBJECT(TelnetAppender)
		BEGIN_LOG4CXX_CAST_MAP()
		LOG4CXX_CAST_ENTRY(TelnetAppender)
		LOG4CXX_CAST_ENTRY_CHAIN(AppenderSkeleton)
		END_LOG4CXX_CAST_MAP()

		TelnetAppender();
		~TelnetAppender();

		/**
		This appender requires a layout to format the text to the
		attached client(s). */
		virtual bool requiresLayout() const
		{
			return true;
		}

		LogString getEncoding() const;
		void setEncoding(const LogString& value);


		/** all of the options have been set, create the socket handler and
		wait for connections. */
		void activateOptions(log4cxx::helpers::Pool& p);

		/**
		Set options
		*/
		virtual void setOption(const LogString& option, const LogString& value);

		/**
		Returns value of the <b>Port</b> option.
		*/
		int getPort() const
		{
			return port;
		}

		/**
		The <b>Port</b> option takes a positive integer representing
		the port where the server is waiting for connections.
		*/
		void setPort(int port1)
		{
			this->port = port1;
		}


		/** shuts down the appender. */
		void close();

	protected:
		/** Handles a log event.  For this appender, that means writing the
		message to each connected client.  */
		virtual void append(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& p) ;

		//---------------------------------------------------------- SocketHandler:

	private:
		//   prevent copy and assignment statements
		TelnetAppender(const TelnetAppender&);
		TelnetAppender& operator=(const TelnetAppender&);

		void write(log4cxx::helpers::ByteBuffer&);
		void writeStatus(const log4cxx::helpers::SocketPtr& socket, const LogString& msg, log4cxx::helpers::Pool& p);
		ConnectionList connections;
		LogString encoding;
		log4cxx::helpers::CharsetEncoderPtr encoder;
		helpers::ServerSocket* serverSocket;
		log4cxx::thread sh;
		size_t activeConnections;
		void acceptConnections();
}; // class TelnetAppender

LOG4CXX_PTR_DEF(TelnetAppender);
} // namespace net
} // namespace log4cxx


#if defined(_MSC_VER)
	#pragma warning ( pop )
#endif

#endif // _LOG4CXX_NET_TELNET_APPENDER_H

