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