/*
 * 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_SMTP_H
#define _LOG4CXX_NET_SMTP_H


#include <log4cxx/appenderskeleton.h>
#include <log4cxx/helpers/cyclicbuffer.h>
#include <log4cxx/spi/triggeringeventevaluator.h>

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

namespace log4cxx
{
namespace net
{
/**
Send an e-mail when a specific logging event occurs, typically on
errors or fatal errors.
<p>The number of logging events delivered in this e-mail depend on
the value of <b>BufferSize</b> option. The
<code>SMTPAppender</code> keeps only the last
<code>BufferSize</code> logging events in its cyclic buffer. This
keeps memory requirements at a reasonable level while still
delivering useful application context.
*/
class LOG4CXX_EXPORT SMTPAppender : public AppenderSkeleton
{
	private:

	private:
		SMTPAppender(const SMTPAppender&);
		SMTPAppender& operator=(const SMTPAppender&);
		static bool asciiCheck(const LogString& value, const LogString& label);
		/**
		This method determines if there is a sense in attempting to append.
		<p>It checks whether there is a set output target and also if
		there is a set layout. If these checks fail, then the boolean
		value <code>false</code> is returned. */
		bool checkEntryConditions();

		LogString to;
		LogString cc;
		LogString bcc;
		LogString from;
		LogString subject;
		LogString smtpHost;
		LogString smtpUsername;
		LogString smtpPassword;
		int smtpPort;
		int bufferSize; // 512
		bool locationInfo;
		helpers::CyclicBuffer cb;
		spi::TriggeringEventEvaluatorPtr evaluator;

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

		SMTPAppender();
		/**
		The default constructor will instantiate the appender with a
		spi::TriggeringEventEvaluator that will trigger on events with
		level ERROR or higher.*/
		SMTPAppender(log4cxx::helpers::Pool& p);

		/**
		Use <code>evaluator</code> passed as parameter as the
		spi::TriggeringEventEvaluator for this net::SMTPAppender.
		*/
		SMTPAppender(spi::TriggeringEventEvaluatorPtr evaluator);

		~SMTPAppender();

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

		/**
		Activate the specified options, such as the smtp host, the
		recipient, from, etc.
		*/
		virtual void activateOptions(log4cxx::helpers::Pool& p);

		/**
		Perform SMTPAppender specific appending actions, mainly adding
		the event to a cyclic buffer and checking if the event triggers
		an e-mail to be sent. */
		virtual void append(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& p);


		virtual void close();

		/**
		Returns value of the <b>To</b> option.
		*/
		LogString getTo() const;

		/**
		Returns value of the <b>cc</b> option.
		*/
		LogString getCc() const;

		/**
		Returns value of the <b>bcc</b> option.
		*/
		LogString getBcc() const;


		/**
		The <code>SMTPAppender</code> requires a {@link
		Layout layout}.  */
		virtual bool requiresLayout() const;

		/**
		Send the contents of the cyclic buffer as an e-mail message.
		*/
		void sendBuffer(log4cxx::helpers::Pool& p);


		/**
		Returns value of the <b>EvaluatorClass</b> option.
		*/
		LogString getEvaluatorClass();

		/**
		Returns value of the <b>From</b> option.
		*/
		LogString getFrom() const;

		/**
		Returns value of the <b>Subject</b> option.
		*/
		LogString getSubject() const;


		/**
		The <b>From</b> option takes a string value which should be a
		e-mail address of the sender.
		*/
		void setFrom(const LogString& from);

		/**
		The <b>Subject</b> option takes a string value which should be a
		the subject of the e-mail message.
		*/
		void setSubject(const LogString& subject);

		/**
		The <b>BufferSize</b> option takes a positive integer
		representing the maximum number of logging events to collect in a
		cyclic buffer. When the <code>BufferSize</code> is reached,
		oldest events are deleted as new events are added to the
		buffer. By default the size of the cyclic buffer is 512 events.
		*/
		void setBufferSize(int bufferSize);

		/**
		The <b>SMTPHost</b> option takes a string value which should be a
		the host name of the SMTP server that will send the e-mail message.
		*/
		void setSMTPHost(const LogString& smtpHost);

		/**
		Returns value of the <b>SMTPHost</b> option.
		*/
		LogString getSMTPHost() const;

		/**
		The <b>SMTPPort</b> option takes a string value which should be a
		the port of the SMTP server that will send the e-mail message.
		*/
		void setSMTPPort(int port);

		/**
		Returns value of the <b>SMTPHost</b> option.
		*/
		int getSMTPPort() const;

		/**
		The <b>To</b> option takes a string value which should be a
		comma separated list of e-mail address of the recipients.
		*/
		void setTo(const LogString& to);

		/**
		The <b>Cc</b> option takes a string value which should be a
		comma separated list of e-mail address of the cc'd recipients.
		*/
		void setCc(const LogString& to);

		/**
		The <b>Bcc</b> option takes a string value which should be a
		comma separated list of e-mail address of the bcc'd recipients.
		*/
		void setBcc(const LogString& to);


		/**
		The <b>SMTPUsername</b> option takes a string value which should be a
		the user name for the SMTP server.
		*/
		void setSMTPUsername(const LogString& newVal);

		/**
		Returns value of the <b>SMTPUsername</b> option.
		*/
		LogString getSMTPUsername() const;

		/**
		The <b>SMTPPassword</b> option takes a string value which should be a
		the password for the SMTP server.
		*/
		void setSMTPPassword(const LogString& newVal);

		/**
		Returns value of the <b>SMTPPassword</b> option.
		*/
		LogString getSMTPPassword() const;

		/**
		Returns value of the <b>BufferSize</b> option.
		*/
		inline int getBufferSize() const
		{
			return bufferSize;
		}


		/**
		 *   Gets the current triggering evaluator.
		 *   @return triggering evaluator.
		 */
		log4cxx::spi::TriggeringEventEvaluatorPtr getEvaluator() const;

		/**
		 *   Sets the triggering evaluator.
		 *   @param trigger triggering evaluator.
		 */
		void setEvaluator(log4cxx::spi::TriggeringEventEvaluatorPtr& trigger);

		/**
		The <b>EvaluatorClass</b> option takes a string value
		representing the name of the class implementing the
		spi::TriggeringEventEvaluator interface. A corresponding object will
		be instantiated and assigned as the triggering event evaluator
		for the SMTPAppender.
		*/
		void setEvaluatorClass(const LogString& value);

		/**
		The <b>LocationInfo</b> option is provided for compatibility with log4j
		and has no effect in log4cxx.
		*/
		void setLocationInfo(bool locationInfo);

		/**
		Returns value of the <b>LocationInfo</b> option.
		*/
		bool getLocationInfo() const;
}; // class SMTPAppender

LOG4CXX_PTR_DEF(SMTPAppender);

}  // namespace net
} // namespace log4cxx

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

#endif // _LOG4CXX_NET_SMTP_H
