/*
 * 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_SOCKET_APPENDER_SKELETON_H
#define _LOG4CXX_NET_SOCKET_APPENDER_SKELETON_H

#include <log4cxx/appenderskeleton.h>
#include <log4cxx/helpers/socket.h>
#include <log4cxx/helpers/thread.h>
#include <log4cxx/helpers/objectoutputstream.h>

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

namespace log4cxx
{

namespace net
{

/**
 *  Abstract base class for SocketAppender and XMLSocketAppender
 */
class LOG4CXX_EXPORT SocketAppenderSkeleton : public AppenderSkeleton
{
	private:
		/**
		host name
		*/
		LogString remoteHost;

		/**
		IP address
		*/
		helpers::InetAddressPtr address;

		int port;
		int reconnectionDelay;
		bool locationInfo;

	public:
		SocketAppenderSkeleton(int defaultPort, int reconnectionDelay);
		~SocketAppenderSkeleton();

		/**
		Connects to remote server at <code>address</code> and <code>port</code>.
		*/
		SocketAppenderSkeleton(helpers::InetAddressPtr address, int port, int reconnectionDelay);

		/**
		Connects to remote server at <code>host</code> and <code>port</code>.
		*/
		SocketAppenderSkeleton(const LogString& host, int port, int reconnectionDelay);

		/**
		Connect to the specified <b>RemoteHost</b> and <b>Port</b>.
		*/
		void activateOptions(log4cxx::helpers::Pool& p);

		void close();


		/**
		* This appender does not use a layout. Hence, this method
		* returns <code>false</code>.
		*
		     */
		bool requiresLayout() const
		{
			return false;
		}

		/**
		* The <b>RemoteHost</b> option takes a string value which should be
		* the host name of the server where a
		* Apache Chainsaw or compatible is running.
		* */
		inline void setRemoteHost(const LogString& host)
		{
			address = helpers::InetAddress::getByName(host);
			remoteHost.assign(host);
		}

		/**
		Returns value of the <b>RemoteHost</b> option.
		*/
		inline const LogString& getRemoteHost() const
		{
			return remoteHost;
		}

		/**
		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;
		}

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

		/**
		The <b>LocationInfo</b> option takes a boolean value. If true,
		the information sent to the remote host will include location
		information. By default no location information is sent to the server.
		*/
		void setLocationInfo(bool locationInfo1)
		{
			this->locationInfo = locationInfo1;
		}

		/**
		Returns value of the <b>LocationInfo</b> option.
		*/
		bool getLocationInfo() const
		{
			return locationInfo;
		}

		/**
		The <b>ReconnectionDelay</b> option takes a positive integer
		representing the number of milliseconds to wait between each
		failed connection attempt to the server. The default value of
		this option is 30000 which corresponds to 30 seconds.

		<p>Setting this option to zero turns off reconnection
		capability.
		*/
		void setReconnectionDelay(int reconnectionDelay1)
		{
			this->reconnectionDelay = reconnectionDelay1;
		}

		/**
		Returns value of the <b>ReconnectionDelay</b> option.
		*/
		int getReconnectionDelay() const
		{
			return reconnectionDelay;
		}

		void fireConnector();

		void setOption(const LogString& option,
			const LogString& value);

	protected:

		virtual void setSocket(log4cxx::helpers::SocketPtr& socket, log4cxx::helpers::Pool& p) = 0;

		virtual void cleanUp(log4cxx::helpers::Pool& p) = 0;

		virtual int getDefaultDelay() const = 0;

		virtual int getDefaultPort() const = 0;

	private:
		void connect(log4cxx::helpers::Pool& p);
		/**
		     The Connector will reconnect when the server becomes available
		     again.  It does this by attempting to open a new connection every
		     <code>reconnectionDelay</code> milliseconds.

		     <p>It stops trying whenever a connection is established. It will
		     restart to try reconnect to the server when previously open
		     connection is droppped.
		     */

		helpers::Thread thread;
		static void* LOG4CXX_THREAD_FUNC monitor(apr_thread_t* thread, void* data);
		SocketAppenderSkeleton(const SocketAppenderSkeleton&);
		SocketAppenderSkeleton& operator=(const SocketAppenderSkeleton&);

}; // class SocketAppenderSkeleton
} // namespace net
} // namespace log4cxx

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

#endif // _LOG4CXX_NET_SOCKET_APPENDER_SKELETON_H

