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



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_forms.hxx"
#include "limitedformats.hxx"
#include "services.hxx"
#include <osl/diagnose.h>
#include <comphelper/types.hxx>
#include <comphelper/extract.hxx>
#include <com/sun/star/form/FormComponentType.hpp>

//.........................................................................
namespace frm
{
//.........................................................................

	using namespace ::com::sun::star::uno;
	using namespace ::com::sun::star::util;
	using namespace ::com::sun::star::lang;
	using namespace ::com::sun::star::form;
	using namespace ::com::sun::star::beans;

	sal_Int32								OLimitedFormats::s_nInstanceCount(0);
	::osl::Mutex							OLimitedFormats::s_aMutex;
	Reference< XNumberFormatsSupplier >		OLimitedFormats::s_xStandardFormats;

	//=====================================================================
	//=
	//=====================================================================
	//---------------------------------------------------------------------
	enum LocaleType
	{
		ltEnglishUS,
		ltGerman,
		ltSystem
	};

	//---------------------------------------------------------------------
	static const Locale& getLocale(LocaleType _eType)
	{
		static const Locale s_aEnglishUS( ::rtl::OUString::createFromAscii("en"), ::rtl::OUString::createFromAscii("us"), ::rtl::OUString() );
		static const Locale s_aGerman( ::rtl::OUString::createFromAscii("de"), ::rtl::OUString::createFromAscii("DE"), ::rtl::OUString() );
		static const ::rtl::OUString s_sEmptyString;
		static const Locale s_aSystem( s_sEmptyString, s_sEmptyString, s_sEmptyString );

		switch (_eType)
		{
			case ltEnglishUS:
				return s_aEnglishUS;

			case ltGerman:
				return s_aGerman;

			case ltSystem:
				return s_aSystem;
		}

		OSL_ENSURE(sal_False, "getLocale: invalid enum value!");
		return s_aSystem;
	}

	//---------------------------------------------------------------------
	struct FormatEntry
	{
		const sal_Char* pDescription;
		sal_Int32		nKey;
		LocaleType		eLocale;
	};

	//---------------------------------------------------------------------
	static const FormatEntry* lcl_getFormatTable(sal_Int16 nTableId)
	{
		switch (nTableId)
		{
			case FormComponentType::TIMEFIELD:
			{
				static FormatEntry s_aFormats[] = {
					{ "HH:MM", -1, ltEnglishUS },
					{ "HH:MM:SS", -1, ltEnglishUS },
					{ "HH:MM AM/PM", -1, ltEnglishUS },
					{ "HH:MM:SS AM/PM", -1, ltEnglishUS },
					{ NULL, -1, ltSystem }
				};
				// don't switch this table here to const. The compiler could be tempted to really place this
				// in a non-writeable segment, but we want to fill in the format keys later ....
				return s_aFormats;
			}
			case FormComponentType::DATEFIELD:
			{
				static FormatEntry s_aFormats[] = {
					{ "T-M-JJ", -1, ltGerman },
					{ "TT-MM-JJ", -1, ltGerman },
					{ "TT-MM-JJJJ", -1, ltGerman },
					{ "NNNNT. MMMM JJJJ", -1, ltGerman },

					{ "DD/MM/YY", -1, ltEnglishUS },
					{ "MM/DD/YY", -1, ltEnglishUS },
					{ "YY/MM/DD", -1, ltEnglishUS },
					{ "DD/MM/YYYY", -1, ltEnglishUS },
					{ "MM/DD/YYYY", -1, ltEnglishUS },
					{ "YYYY/MM/DD", -1, ltEnglishUS },

					{ "JJ-MM-TT", -1, ltGerman },
					{ "JJJJ-MM-TT", -1, ltGerman },

					{ NULL, -1, ltSystem }
				};
				return s_aFormats;
			}
		}

		OSL_ENSURE(sal_False, "lcl_getFormatTable: invalid id!");
		return NULL;
	}

	//=====================================================================
	//= OLimitedFormats
	//=====================================================================
	//---------------------------------------------------------------------
	OLimitedFormats::OLimitedFormats(const Reference< XMultiServiceFactory >& _rxORB, const sal_Int16 _nClassId)
		:m_nFormatEnumPropertyHandle(-1)
        ,m_nTableId(_nClassId)
	{
		OSL_ENSURE(_rxORB.is(), "OLimitedFormats::OLimitedFormats: invalid service factory!");
		acquireSupplier(_rxORB);
		ensureTableInitialized(m_nTableId);
	}

	//---------------------------------------------------------------------
	OLimitedFormats::~OLimitedFormats()
	{
		releaseSupplier();
	}

	//---------------------------------------------------------------------
	void OLimitedFormats::ensureTableInitialized(const sal_Int16 _nTableId)
	{
		const FormatEntry* pFormatTable = lcl_getFormatTable(_nTableId);
		if (-1 == pFormatTable->nKey)
		{
			::osl::MutexGuard aGuard(s_aMutex);
			if (-1 == pFormatTable->nKey)
			{
				// initialize the keys
				Reference<XNumberFormats> xStandardFormats;
				if (s_xStandardFormats.is())
					xStandardFormats = s_xStandardFormats->getNumberFormats();
				OSL_ENSURE(xStandardFormats.is(), "OLimitedFormats::ensureTableInitialized: don't have a formats supplier!");

				if (xStandardFormats.is())
				{
					// loop through the table
					FormatEntry* pLoopFormats = const_cast<FormatEntry*>(pFormatTable);
					while (pLoopFormats->pDescription)
					{
						// get the key for the description
						pLoopFormats->nKey = xStandardFormats->queryKey(
							::rtl::OUString::createFromAscii(pLoopFormats->pDescription),
							getLocale(pLoopFormats->eLocale),
							sal_False
						);

						if (-1 == pLoopFormats->nKey)
						{
							pLoopFormats->nKey = xStandardFormats->addNew(
								::rtl::OUString::createFromAscii(pLoopFormats->pDescription),
								getLocale(pLoopFormats->eLocale)
							);
#ifdef DBG_UTIL
							try
							{
								xStandardFormats->getByKey(pLoopFormats->nKey);
							}
							catch(const Exception&)
							{
								OSL_ENSURE(sal_False, "OLimitedFormats::ensureTableInitialized: adding the key to the formats collection failed!");
							}
#endif
						}

						// next
						++pLoopFormats;
					}
				}
			}
		}
	}

	//---------------------------------------------------------------------
	void OLimitedFormats::clearTable(const sal_Int16 _nTableId)
	{
		::osl::MutexGuard aGuard(s_aMutex);
		const FormatEntry* pFormats = lcl_getFormatTable(_nTableId);
		FormatEntry* pResetLoop = const_cast<FormatEntry*>(pFormats);
		while (pResetLoop->pDescription)
		{
			pResetLoop->nKey = -1;
			++pResetLoop;
		}
	}

	//---------------------------------------------------------------------
	void OLimitedFormats::setAggregateSet(const Reference< XFastPropertySet >& _rxAggregate, sal_Int32 _nOriginalPropertyHandle)
	{
		// changes (NULL -> not NULL) and (not NULL -> NULL) are allowed
		OSL_ENSURE(!m_xAggregate.is() || !_rxAggregate.is(), "OLimitedFormats::setAggregateSet: already have an aggregate!");
		OSL_ENSURE(_rxAggregate.is() || m_xAggregate.is(), "OLimitedFormats::setAggregateSet: invalid new aggregate!");

		m_xAggregate = _rxAggregate;
		m_nFormatEnumPropertyHandle = _nOriginalPropertyHandle;
#ifdef DBG_UTIL
		if (m_xAggregate.is())
		{
			try
			{
				m_xAggregate->getFastPropertyValue(m_nFormatEnumPropertyHandle);
			}
			catch(const Exception&)
			{
				OSL_ENSURE(sal_False, "OLimitedFormats::setAggregateSet: invalid handle!");
			}
		}
#endif
	}

	//---------------------------------------------------------------------
	void OLimitedFormats::getFormatKeyPropertyValue( Any& _rValue ) const
	{
		_rValue.clear();

		OSL_ENSURE(m_xAggregate.is() && (-1 != m_nFormatEnumPropertyHandle), "OLimitedFormats::getFormatKeyPropertyValue: not initialized!");
		if (m_xAggregate.is())
		{
			// get the aggregate's enum property value
			Any aEnumPropertyValue = m_xAggregate->getFastPropertyValue(m_nFormatEnumPropertyHandle);
			sal_Int32 nValue = -1;
			::cppu::enum2int(nValue, aEnumPropertyValue);

			// get the translation table
			const FormatEntry* pFormats = lcl_getFormatTable(m_nTableId);

			// seek to the nValue'th entry
			sal_Int32 nLookup = 0;
			for	(	;
					(NULL != pFormats->pDescription) && (nLookup < nValue);
					++pFormats, ++nLookup
				)
				;
			OSL_ENSURE(NULL != pFormats->pDescription, "OLimitedFormats::getFormatKeyPropertyValue: did not find the value!");
			if (pFormats->pDescription)
				_rValue <<= pFormats->nKey;
		}

		// TODO: should use a standard format for the control type we're working for
	}

	//---------------------------------------------------------------------
	sal_Bool OLimitedFormats::convertFormatKeyPropertyValue(Any& _rConvertedValue, Any& _rOldValue, const Any& _rNewValue)
	{
		OSL_ENSURE(m_xAggregate.is() && (-1 != m_nFormatEnumPropertyHandle), "OLimitedFormats::convertFormatKeyPropertyValue: not initialized!");

		if (m_xAggregate.is())
		{
			// the new format key to set
			sal_Int32 nNewFormat = 0;
			if (!(_rNewValue >>= nNewFormat))
				throw IllegalArgumentException();

			// get the old (enum) value from the aggregate
			Any aEnumPropertyValue = m_xAggregate->getFastPropertyValue(m_nFormatEnumPropertyHandle);
			sal_Int32 nOldEnumValue = -1;
			::cppu::enum2int(nOldEnumValue, aEnumPropertyValue);

			// get the translation table
			const FormatEntry* pFormats = lcl_getFormatTable(m_nTableId);

			_rOldValue.clear();
			_rConvertedValue.clear();

			// look for the entry with the given format key
			sal_Int32 nTablePosition = 0;
			for	(	;
					(NULL != pFormats->pDescription) && (nNewFormat != pFormats->nKey);
					++pFormats, ++nTablePosition
				)
			{
				if (nTablePosition == nOldEnumValue)
					_rOldValue <<= pFormats->nKey;
			}

			sal_Bool bFoundIt = (NULL != pFormats->pDescription);
			sal_Bool bModified = sal_False;
			if (bFoundIt)
			{
				_rConvertedValue <<= (sal_Int16)nTablePosition;
				bModified = nTablePosition != nOldEnumValue;
			}

			if (!_rOldValue.hasValue())
			{	// did not reach the end of the table (means we found nNewFormat)
				// -> go to the end to ensure that _rOldValue is set
				while (pFormats->pDescription)
				{
					if (nTablePosition == nOldEnumValue)
					{
						_rOldValue <<= pFormats->nKey;
						break;
					}

					++pFormats;
					++nTablePosition;
				}
			}

			OSL_ENSURE(_rOldValue.hasValue(), "OLimitedFormats::convertFormatKeyPropertyValue: did not find the old enum value in the table!");

			if (!bFoundIt)
			{	// somebody gave us an format which we can't translate
				::rtl::OUString sMessage = ::rtl::OUString::createFromAscii("This control supports only a very limited number of formats.");
				throw IllegalArgumentException(sMessage, NULL, 2);
			}

			return bModified;
		}

		return sal_False;
	}

	//---------------------------------------------------------------------
	void OLimitedFormats::setFormatKeyPropertyValue( const Any& _rNewValue )
	{
		OSL_ENSURE(m_xAggregate.is() && (-1 != m_nFormatEnumPropertyHandle), "OLimitedFormats::setFormatKeyPropertyValue: not initialized!");

		if (m_xAggregate.is())
		{	// this is to be called after convertFormatKeyPropertyValue, where
			// we translated the format key into a enum value.
			// So now we can simply forward this enum value to our aggreate
			m_xAggregate->setFastPropertyValue(m_nFormatEnumPropertyHandle, _rNewValue);
		}
	}

	//---------------------------------------------------------------------
	void OLimitedFormats::acquireSupplier(const Reference< XMultiServiceFactory >& _rxORB)
	{
		::osl::MutexGuard aGuard(s_aMutex);
		if ((1 == ++s_nInstanceCount) && _rxORB.is())
		{	// create the standard formatter

			Sequence< Any > aInit(1);
			aInit[0] <<= getLocale(ltEnglishUS);

			Reference< XInterface > xSupplier = _rxORB->createInstanceWithArguments(FRM_NUMBER_FORMATS_SUPPLIER, aInit);
			OSL_ENSURE(xSupplier.is(), "OLimitedFormats::OLimitedFormats: could not create a formats supplier!");

			s_xStandardFormats = Reference< XNumberFormatsSupplier >(xSupplier, UNO_QUERY);
			OSL_ENSURE(s_xStandardFormats.is() || !xSupplier.is(), "OLimitedFormats::OLimitedFormats: missing an interface!");
		}
	}

	//---------------------------------------------------------------------
	void OLimitedFormats::releaseSupplier()
	{
		::osl::MutexGuard aGuard(s_aMutex);
		if (0 == --s_nInstanceCount)
		{
			::comphelper::disposeComponent(s_xStandardFormats);
			s_xStandardFormats = NULL;

			clearTable(FormComponentType::TIMEFIELD);
			clearTable(FormComponentType::DATEFIELD);
		}
	}

//.........................................................................
}	// namespace frm
//.........................................................................

