/**************************************************************
 * 
 * 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_unotools.hxx"
#include <unotools/inetoptions.hxx>
#include "rtl/instance.hxx"
#include <tools/urlobj.hxx>
#ifndef _WILDCARD_HXX
#include <tools/wldcrd.hxx>
#endif

#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <utility>
#include <com/sun/star/beans/PropertyChangeEvent.hpp>
#include <com/sun/star/beans/XPropertiesChangeListener.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/uno/Exception.hpp>
#include <com/sun/star/uno/Reference.hxx>
#include <com/sun/star/uno/RuntimeException.hpp>
#include <osl/mutex.hxx>
#include <rtl/ustring.h>
#include <rtl/ustring.hxx>
#include <sal/types.h>
#include <unotools/configitem.hxx>
#include <unotools/processfactory.hxx>
#include <osl/diagnose.h>
#include <salhelper/refobj.hxx>
#include <rtl/logfile.hxx>
#include "itemholder1.hxx"

using namespace com::sun;

//============================================================================
//
//  takeAny
//
//============================================================================

namespace {

template< typename T > inline T takeAny(star::uno::Any const & rAny)
{
	T aValue = T();
	rAny >>= aValue;
	return aValue;
}

}

//============================================================================
//
//  SvtInetOptions::Impl
//
//============================================================================

class SvtInetOptions::Impl: public salhelper::ReferenceObject,
                            public utl::ConfigItem
{
public:
	enum Index
	{
		INDEX_NO_PROXY,
		INDEX_PROXY_TYPE,
		INDEX_FTP_PROXY_NAME,
		INDEX_FTP_PROXY_PORT,
		INDEX_HTTP_PROXY_NAME,
		INDEX_HTTP_PROXY_PORT
	};

	Impl();

	star::uno::Any getProperty(Index nIndex);

	void
    setProperty(Index nIndex, star::uno::Any const & rValue, bool bFlush);

	inline void flush() { Commit(); }

	void
	addPropertiesChangeListener(
		star::uno::Sequence< rtl::OUString > const & rPropertyNames,
		star::uno::Reference< star::beans::XPropertiesChangeListener > const &
            rListener);

	void
	removePropertiesChangeListener(
		star::uno::Sequence< rtl::OUString > const & rPropertyNames,
		star::uno::Reference< star::beans::XPropertiesChangeListener > const &
            rListener);

private:
	enum { ENTRY_COUNT = INDEX_HTTP_PROXY_PORT + 1 };

	struct Entry
	{
		enum State { UNKNOWN, KNOWN, MODIFIED };

		inline Entry(): m_eState(UNKNOWN) {}

		rtl::OUString m_aName;
		star::uno::Any m_aValue;
		State m_eState;
	};

	// MSVC has problems with the below Map type when
	// star::uno::Reference< star::beans::XPropertiesChangeListener > is not
    // wrapped in class Listener:
	class Listener:
        public star::uno::Reference< star::beans::XPropertiesChangeListener >
	{
	public:
		Listener(star::uno::Reference<
                         star::beans::XPropertiesChangeListener > const &
				     rListener):
			star::uno::Reference< star::beans::XPropertiesChangeListener >(
                rListener)
        {}
	};

	typedef std::map< Listener, std::set< rtl::OUString > > Map;

	osl::Mutex m_aMutex;
	Entry m_aEntries[ENTRY_COUNT];
	Map m_aListeners;

	virtual inline ~Impl() { Commit(); }

	virtual void Notify(star::uno::Sequence< rtl::OUString > const & rKeys);

	virtual void Commit();

	void notifyListeners(star::uno::Sequence< rtl::OUString > const & rKeys);
};

//============================================================================
// virtual
void
SvtInetOptions::Impl::Notify(star::uno::Sequence< rtl::OUString > const &
                                 rKeys)
{
	{
		osl::MutexGuard aGuard(m_aMutex);
		for (sal_Int32 i = 0; i < rKeys.getLength(); ++i)
			for (sal_Int32 j = 0; j < ENTRY_COUNT; ++j)
				if (rKeys[i] == m_aEntries[j].m_aName)
				{
					m_aEntries[j].m_eState = Entry::UNKNOWN;
					break;
				}
	}
	notifyListeners(rKeys);
}

//============================================================================
// virtual
void SvtInetOptions::Impl::Commit()
{
	star::uno::Sequence< rtl::OUString > aKeys(ENTRY_COUNT);
	star::uno::Sequence< star::uno::Any > aValues(ENTRY_COUNT);
	sal_Int32 nCount = 0;
	{
		osl::MutexGuard aGuard(m_aMutex);
		for (sal_Int32 i = 0; i < ENTRY_COUNT; ++i)
			if (m_aEntries[i].m_eState == Entry::MODIFIED)
			{
				aKeys[nCount] = m_aEntries[i].m_aName;
				aValues[nCount] = m_aEntries[i].m_aValue;
				++nCount;
				m_aEntries[i].m_eState = Entry::KNOWN;
			}
	}
	if (nCount > 0)
	{
		aKeys.realloc(nCount);
		aValues.realloc(nCount);
		PutProperties(aKeys, aValues);
	}
}

//============================================================================
void
SvtInetOptions::Impl::notifyListeners(
    star::uno::Sequence< rtl::OUString > const & rKeys)
{
		typedef std::pair< star::uno::Reference< star::beans::XPropertiesChangeListener >,
		                   star::uno::Sequence< star::beans::PropertyChangeEvent > > Listen2EventPair;
		typedef std::vector< Listen2EventPair > NotificationList;
	NotificationList aNotifications;
	{
		osl::MutexGuard aGuard(m_aMutex);
		aNotifications.reserve(m_aListeners.size());
		Map::const_iterator aMapEnd(m_aListeners.end());
		for (Map::const_iterator aIt(m_aListeners.begin()); aIt != aMapEnd;
			 ++aIt)
		{
			const Map::mapped_type &rSet = aIt->second;
			Map::mapped_type::const_iterator aSetEnd(rSet.end());
			star::uno::Sequence< star::beans::PropertyChangeEvent >
				aEvents(rKeys.getLength());
			sal_Int32 nCount = 0;
			for (sal_Int32 i = 0; i < rKeys.getLength(); ++i)
			{
				rtl::OUString
					aTheKey(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
						                      "Inet/")));
				aTheKey += rKeys[i];
				if (rSet.find(aTheKey) != aSetEnd)
				{
					aEvents[nCount].PropertyName = aTheKey;
					aEvents[nCount].PropertyHandle = -1;
					++nCount;
				}
			}
			if (nCount > 0)
				aNotifications.push_back( Listen2EventPair( aIt->first, aEvents));
		}
	}
	for (NotificationList::size_type i = 0; i < aNotifications.size(); ++i)
		if (aNotifications[i].first.is())
			aNotifications[i].first->
				propertiesChange(aNotifications[i].second);
}

//============================================================================
SvtInetOptions::Impl::Impl():
	ConfigItem(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Inet/Settings")))
{
	m_aEntries[INDEX_NO_PROXY].m_aName
		= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ooInetNoProxy"));
	m_aEntries[INDEX_PROXY_TYPE].m_aName
		= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ooInetProxyType"));
	m_aEntries[INDEX_FTP_PROXY_NAME].m_aName
		= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ooInetFTPProxyName"));
	m_aEntries[INDEX_FTP_PROXY_PORT].m_aName
		= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ooInetFTPProxyPort"));
	m_aEntries[INDEX_HTTP_PROXY_NAME].m_aName
		= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ooInetHTTPProxyName"));
	m_aEntries[INDEX_HTTP_PROXY_PORT].m_aName
		= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ooInetHTTPProxyPort"));

	star::uno::Sequence< rtl::OUString > aKeys(ENTRY_COUNT);
	for (sal_Int32 i = 0; i < ENTRY_COUNT; ++i)
		aKeys[i] = m_aEntries[i].m_aName;
	if (!EnableNotification(aKeys))
		OSL_ENSURE(false,
				   "SvtInetOptions::Impl::Impl(): Bad EnableNotifications()");
}

//============================================================================
star::uno::Any SvtInetOptions::Impl::getProperty(Index nPropIndex)
{
	for (int nTryCount = 0; nTryCount < 10; ++nTryCount)
	{
		{
			osl::MutexGuard aGuard(m_aMutex);
			if (m_aEntries[nPropIndex].m_eState != Entry::UNKNOWN)
				return m_aEntries[nPropIndex].m_aValue;
		}
		star::uno::Sequence< rtl::OUString > aKeys(ENTRY_COUNT);
		int nIndices[ENTRY_COUNT];
		sal_Int32 nCount = 0;
		{
			osl::MutexGuard aGuard(m_aMutex);
			for (int i = 0; i < ENTRY_COUNT; ++i)
				if (m_aEntries[i].m_eState == Entry::UNKNOWN)
				{
					aKeys[nCount] = m_aEntries[i].m_aName;
					nIndices[nCount] = i;
					++nCount;
				}
		}
		if (nCount > 0)
		{
			aKeys.realloc(nCount);
			star::uno::Sequence< star::uno::Any >
                aValues(GetProperties(aKeys));
			OSL_ENSURE(aValues.getLength() == nCount,
					   "SvtInetOptions::Impl::getProperty():"
					       " Bad GetProperties() result");
			nCount = std::min(nCount, aValues.getLength());
			{
				osl::MutexGuard aGuard(m_aMutex);
				for (sal_Int32 i = 0; i < nCount; ++i)
				{
					int nIndex = nIndices[i];
					if (m_aEntries[nIndex].m_eState == Entry::UNKNOWN)
					{
						m_aEntries[nIndices[i]].m_aValue = aValues[i];
						m_aEntries[nIndices[i]].m_eState = Entry::KNOWN;
					}
				}
			}
		}
	}
	OSL_ENSURE(false,
			   "SvtInetOptions::Impl::getProperty(): Possible life lock");
	{
		osl::MutexGuard aGuard(m_aMutex);
		return m_aEntries[nPropIndex].m_aValue;
	}
}

//============================================================================
void SvtInetOptions::Impl::setProperty(Index nIndex,
                                       star::uno::Any const & rValue,
									   bool bFlush)
{
	SetModified();
	{
		osl::MutexGuard aGuard(m_aMutex);
		m_aEntries[nIndex].m_aValue = rValue;
		m_aEntries[nIndex].m_eState = bFlush ? Entry::KNOWN : Entry::MODIFIED;
	}

	star::uno::Sequence< rtl::OUString > aKeys(1);
	aKeys[0] = m_aEntries[nIndex].m_aName;
	if (bFlush)
	{
		star::uno::Sequence< star::uno::Any > aValues(1);
		aValues[0] = rValue;
		PutProperties(aKeys, aValues);
	}
	else
		notifyListeners(aKeys);
}

//============================================================================
void
SvtInetOptions::Impl::addPropertiesChangeListener(
	star::uno::Sequence< rtl::OUString > const & rPropertyNames,
	star::uno::Reference< star::beans::XPropertiesChangeListener > const &
        rListener)
{
	osl::MutexGuard aGuard(m_aMutex);
	Map::mapped_type & rEntry = m_aListeners[rListener];
	for (sal_Int32 i = 0; i < rPropertyNames.getLength(); ++i)
		rEntry.insert(rPropertyNames[i]);
}

//============================================================================
void
SvtInetOptions::Impl::removePropertiesChangeListener(
	star::uno::Sequence< rtl::OUString > const & rPropertyNames,
	star::uno::Reference< star::beans::XPropertiesChangeListener > const &
        rListener)
{
	osl::MutexGuard aGuard(m_aMutex);
	Map::iterator aIt(m_aListeners.find(rListener));
	if (aIt != m_aListeners.end())
	{
		for (sal_Int32 i = 0; i < rPropertyNames.getLength(); ++i)
			aIt->second.erase(rPropertyNames[i]);
		if (aIt->second.empty())
			m_aListeners.erase(aIt);
	}
}

//============================================================================
//
//  SvtInetOptions
//
//============================================================================

namespace
{
    class LocalSingleton : public rtl::Static< osl::Mutex, LocalSingleton >
    {
    };
}

// static
SvtInetOptions::Impl * SvtInetOptions::m_pImpl = 0;

//============================================================================
SvtInetOptions::SvtInetOptions()
{
    osl::MutexGuard aGuard(LocalSingleton::get());
	if (!m_pImpl)
    {
        RTL_LOGFILE_CONTEXT(aLog, "unotools ( ??? ) ::SvtInetOptions_Impl::ctor()");
		m_pImpl = new Impl;

        ItemHolder1::holdConfigItem(E_INETOPTIONS);
    }
	m_pImpl->acquire();
}

//============================================================================
SvtInetOptions::~SvtInetOptions()
{
    osl::MutexGuard aGuard(LocalSingleton::get());
	if (m_pImpl->release() == 0)
		m_pImpl = 0;
}

//============================================================================
rtl::OUString SvtInetOptions::GetProxyNoProxy() const
{
	return takeAny< rtl::OUString >(m_pImpl->
									    getProperty(Impl::INDEX_NO_PROXY));
}

//============================================================================
sal_Int32 SvtInetOptions::GetProxyType() const
{
	return takeAny< sal_Int32 >(m_pImpl->
								    getProperty(Impl::INDEX_PROXY_TYPE));
}

//============================================================================
rtl::OUString SvtInetOptions::GetProxyFtpName() const
{
	return takeAny< rtl::OUString >(m_pImpl->
									    getProperty(
											Impl::INDEX_FTP_PROXY_NAME));
}

//============================================================================
sal_Int32 SvtInetOptions::GetProxyFtpPort() const
{
	return takeAny< sal_Int32 >(m_pImpl->
								    getProperty(Impl::INDEX_FTP_PROXY_PORT));
}

//============================================================================
rtl::OUString SvtInetOptions::GetProxyHttpName() const
{
	return takeAny< rtl::OUString >(m_pImpl->
									    getProperty(
											Impl::INDEX_HTTP_PROXY_NAME));
}

//============================================================================
sal_Int32 SvtInetOptions::GetProxyHttpPort() const
{
	return takeAny< sal_Int32 >(m_pImpl->
								    getProperty(Impl::INDEX_HTTP_PROXY_PORT));
}

//============================================================================
void SvtInetOptions::SetProxyNoProxy(rtl::OUString const & rValue,
									 bool bFlush)
{
	m_pImpl->setProperty(Impl::INDEX_NO_PROXY,
						 star::uno::makeAny(rValue),
						 bFlush);
}

//============================================================================
void SvtInetOptions::SetProxyType(ProxyType eValue, bool bFlush)
{
	m_pImpl->setProperty(Impl::INDEX_PROXY_TYPE,
						 star::uno::makeAny(sal_Int32(eValue)),
						 bFlush);
}

//============================================================================
void SvtInetOptions::SetProxyFtpName(rtl::OUString const & rValue,
									 bool bFlush)
{
	m_pImpl->setProperty(Impl::INDEX_FTP_PROXY_NAME,
						 star::uno::makeAny(rValue),
						 bFlush);
}

//============================================================================
void SvtInetOptions::SetProxyFtpPort(sal_Int32 nValue, bool bFlush)
{
	m_pImpl->setProperty(Impl::INDEX_FTP_PROXY_PORT,
						 star::uno::makeAny(nValue),
						 bFlush);
}

//============================================================================
void SvtInetOptions::SetProxyHttpName(rtl::OUString const & rValue,
									  bool bFlush)
{
	m_pImpl->setProperty(Impl::INDEX_HTTP_PROXY_NAME,
						 star::uno::makeAny(rValue),
						 bFlush);
}

//============================================================================
void SvtInetOptions::SetProxyHttpPort(sal_Int32 nValue, bool bFlush)
{
	m_pImpl->setProperty(Impl::INDEX_HTTP_PROXY_PORT,
						 star::uno::makeAny(nValue),
						 bFlush);
}

//============================================================================
void SvtInetOptions::flush()
{
	m_pImpl->flush();
}

//============================================================================
void
SvtInetOptions::addPropertiesChangeListener(
	star::uno::Sequence< rtl::OUString > const & rPropertyNames,
	star::uno::Reference< star::beans::XPropertiesChangeListener > const &
        rListener)
{
	m_pImpl->addPropertiesChangeListener(rPropertyNames, rListener);
}

//============================================================================
void
SvtInetOptions::removePropertiesChangeListener(
	star::uno::Sequence< rtl::OUString > const & rPropertyNames,
	star::uno::Reference< star::beans::XPropertiesChangeListener > const &
        rListener)
{
	m_pImpl->removePropertiesChangeListener(rPropertyNames, rListener);
}
