/*
 * 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_HELPERS_DATE_LAYOUT_H
#define _LOG4CXX_HELPERS_DATE_LAYOUT_H

#include <log4cxx/layout.h>
#include <log4cxx/helpers/dateformat.h>
#include <log4cxx/helpers/timezone.h>

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

namespace log4cxx
{
namespace helpers
{
/**
This abstract layout takes care of all the date related options and
formatting work.
*/
class LOG4CXX_EXPORT DateLayout : public Layout
{
	private:
		LogString timeZoneID;
		LogString dateFormatOption;

	protected:
		DateFormatPtr dateFormat;

	public:
		DateLayout(const LogString& dateLayoutOption);
		virtual ~DateLayout();

		virtual void activateOptions(log4cxx::helpers::Pool& p);
		virtual void setOption(const LogString& option, const LogString& value);

		/**
		The value of the <b>DateFormat</b> option should be either an
		argument to the constructor of helpers::DateFormat or one of
		the strings <b>"NULL"</b>, <b>"RELATIVE"</b>, <b>"ABSOLUTE"</b>,
		<b>"DATE"</b> or <b>"ISO8601</b>.
		*/
		inline void setDateFormat(const LogString& dateFormat1)
		{
			this->dateFormatOption.assign(dateFormat1);
		}

		/**
		Returns value of the <b>DateFormat</b> option.
		*/
		inline const LogString& getDateFormat() const
		{
			return dateFormatOption;
		}

		/**
		The <b>TimeZoneID</b> option is a time zone ID string in the format
		expected by the <code>locale</code> C++ standard class.
		*/
		inline void setTimeZone(const LogString& timeZone)
		{
			this->timeZoneID.assign(timeZone);
		}

		/**
		Returns value of the <b>TimeZone</b> option.
		*/
		inline const LogString& getTimeZone() const
		{
			return timeZoneID;
		}

		void formatDate(LogString& s,
			const spi::LoggingEventPtr& event,
			log4cxx::helpers::Pool& p) const;

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

};
}  // namespace helpers
} // namespace log4cxx

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

#endif // _LOG4CXX_HELPERS_DATE_LAYOUT_H
