/**************************************************************
 *
 * 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_xmlhelp.hxx"

/**************************************************************************
								TODO
 **************************************************************************

 *************************************************************************/

#include <stdio.h>
#include <osl/file.hxx>
#ifndef _VOS_DIAGNOSE_HXX_
#include <vos/diagnose.hxx>
#endif
#include <ucbhelper/contentidentifier.hxx>
#include <com/sun/star/frame/XConfigManager.hpp>
#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBBUTE_HPP_
#include <com/sun/star/beans/PropertyAttribute.hpp>
#endif
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/container/XContainer.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/container/XNameReplace.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <rtl/bootstrap.hxx>

#include "databases.hxx"
#include "provider.hxx"
#include "content.hxx"
#include "databases.hxx"

using namespace com::sun::star;
using namespace chelp;

//=========================================================================
//=========================================================================
//
// ContentProvider Implementation.
//
//=========================================================================
//=========================================================================

ContentProvider::ContentProvider(
    const uno::Reference< lang::XMultiServiceFactory >& rSMgr )
    : ::ucbhelper::ContentProviderImplHelper( rSMgr ),
        isInitialized( false ),
        m_aScheme( rtl::OUString::createFromAscii( MYUCP_URL_SCHEME ) ),
        m_pDatabases( 0 )
{
}

//=========================================================================
// virtual
ContentProvider::~ContentProvider()
{
	delete m_pDatabases;
}

//=========================================================================
//
// XInterface methods.
//
//=========================================================================

XINTERFACE_IMPL_6( ContentProvider,
				   lang::XTypeProvider,
				   lang::XServiceInfo,
				   ucb::XContentProvider,
				   lang::XComponent,
                   lang::XEventListener, /* base of XContainerListener */
				   container::XContainerListener);

//=========================================================================
//
// XTypeProvider methods.
//
//=========================================================================

XTYPEPROVIDER_IMPL_5( ContentProvider,
				   	  lang::XTypeProvider,
				   	  lang::XServiceInfo,
				   	  ucb::XContentProvider,
					  lang::XComponent,
					  container::XContainerListener);

//=========================================================================
//
// XServiceInfo methods.
//
//=========================================================================

rtl::OUString SAL_CALL ContentProvider::getImplementationName()
	throw( uno::RuntimeException )
{
	return getImplementationName_Static();
}

rtl::OUString ContentProvider::getImplementationName_Static()
{
	return rtl::OUString::createFromAscii("CHelpContentProvider" );
}

sal_Bool SAL_CALL
ContentProvider::supportsService(const rtl::OUString& ServiceName )
	throw( uno::RuntimeException )
{
	uno::Sequence< rtl::OUString > aSNL = getSupportedServiceNames();
	const rtl::OUString* pArray = aSNL.getArray();
	for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
	{
		if( pArray[ i ] == ServiceName )
			return sal_True;
	}

	return sal_False;
}

uno::Sequence< rtl::OUString > SAL_CALL
ContentProvider::getSupportedServiceNames()
	throw( uno::RuntimeException )
{
	return getSupportedServiceNames_Static();
}

static uno::Reference< uno::XInterface > SAL_CALL
ContentProvider_CreateInstance(
 	    const uno::Reference< lang::XMultiServiceFactory> & rSMgr )
	throw( uno::Exception )
{
    lang::XServiceInfo * pX = static_cast< lang::XServiceInfo * >(
        new ContentProvider( rSMgr ) );
    return uno::Reference< uno::XInterface >::query( pX );
}

uno::Sequence< rtl::OUString >
ContentProvider::getSupportedServiceNames_Static()
{
	uno::Sequence< rtl::OUString > aSNS( 2 );
	aSNS.getArray()[ 0 ] =
		rtl::OUString::createFromAscii(
			MYUCP_CONTENT_PROVIDER_SERVICE_NAME1 );
	aSNS.getArray()[ 1 ] =
		rtl::OUString::createFromAscii(
			MYUCP_CONTENT_PROVIDER_SERVICE_NAME2 );

	return aSNS;
}

//=========================================================================
//
// Service factory implementation.
//
//=========================================================================

ONE_INSTANCE_SERVICE_FACTORY_IMPL( ContentProvider );

//=========================================================================
//
// XContentProvider methods.
//
//=========================================================================

// virtual
uno::Reference< ucb::XContent > SAL_CALL
ContentProvider::queryContent(
        const uno::Reference< ucb::XContentIdentifier >& xCanonicId )
    throw( ucb::IllegalIdentifierException, uno::RuntimeException )
{
    if ( !xCanonicId->getContentProviderScheme()
             .equalsIgnoreAsciiCase( m_aScheme ) )
    {   // Wrong URL-scheme
        throw ucb::IllegalIdentifierException();
    }

    {
        osl::MutexGuard aGuard( m_aMutex );
        if( !isInitialized )
            init();
    }

    if( !m_pDatabases )
        throw uno::RuntimeException();

    rtl::OUString aOUString( m_pDatabases->getInstallPathAsURL() );
    rtl::OString aOString( aOUString.getStr(),
                           aOUString.getLength(),
                           RTL_TEXTENCODING_UTF8 );

    // Check, if a content with given id already exists...
    uno::Reference< ucb::XContent > xContent
        = queryExistingContent( xCanonicId ).get();
    if ( xContent.is() )
        return xContent;

    xContent = new Content( m_xSMgr, this, xCanonicId, m_pDatabases );

    // register new content
    registerNewContent( xContent );

    // Further checks

    if ( !xContent->getIdentifier().is() )
        throw ucb::IllegalIdentifierException();

    return xContent;
}

void SAL_CALL
ContentProvider::dispose()
	throw ( uno::RuntimeException)
{
	if(m_xContainer.is())
	{
		m_xContainer->removeContainerListener(this);
		m_xContainer.clear();
	}
}

void SAL_CALL
ContentProvider::elementReplaced(const container::ContainerEvent& Event)
	throw (uno::RuntimeException)
{
	if(!m_pDatabases)
		return;

	rtl::OUString accessor;
	Event.Accessor >>= accessor;
	if(accessor.compareToAscii("HelpStyleSheet"))
		return;

	rtl::OUString replacedElement,element;
	Event.ReplacedElement >>= replacedElement;
	Event.Element >>= element;

	if(replacedElement == element)
		return;

	m_pDatabases->changeCSS(element);
}

void ContentProvider::init()
{
	osl::MutexGuard aGuard( m_aMutex );

	isInitialized = true;
	uno::Reference< lang::XMultiServiceFactory > sProvider(
        getConfiguration() );
    uno::Reference< container::XHierarchicalNameAccess > xHierAccess(
        getHierAccess( sProvider,
                       "org.openoffice.Office.Common" ) );

	rtl::OUString instPath( getKey( xHierAccess,"Path/Current/Help" ) );
	if( ! instPath.getLength() )
		// try to determine path from default
		instPath = rtl::OUString::createFromAscii( "$(instpath)/help" );
	// replace anything like $(instpath);
	subst( instPath );

	rtl::OUString stylesheet( getKey( xHierAccess,"Help/HelpStyleSheet" ) );
	try
    {
		// now adding as configuration change listener for the stylesheet
		uno::Reference< container::XNameAccess> xAccess(
            xHierAccess, uno::UNO_QUERY );
		if( xAccess.is() )
        {
            uno::Any aAny =
                xAccess->getByName( rtl::OUString::createFromAscii( "Help" ) );
            aAny >>= m_xContainer;
            if( m_xContainer.is() )
                m_xContainer->addContainerListener( this );
        }
	}
    catch( uno::Exception const & )
    {
	}

	/**
	 *  now determing
	 *  productname,
	 *  productversion,
	 */

	xHierAccess = getHierAccess( sProvider, "org.openoffice.Setup" );
	rtl::OUString productname(
        getKey( xHierAccess,"Product/ooName" ) );

	rtl::OUString setupversion(
        getKey( xHierAccess,"Product/ooSetupVersion" ) );
    rtl::OUString setupextension;

    try
    {
        uno::Reference< lang::XMultiServiceFactory > xConfigProvider(
	          m_xSMgr ->createInstance(::rtl::OUString::createFromAscii("com.sun.star.configuration.ConfigurationProvider")), uno::UNO_QUERY_THROW);

        uno::Sequence < uno::Any > lParams(1);
        beans::PropertyValue                       aParam ;
        aParam.Name    = ::rtl::OUString::createFromAscii("nodepath");
        aParam.Value <<= ::rtl::OUString::createFromAscii("/org.openoffice.Setup/Product");
        lParams[0] = uno::makeAny(aParam);

        // open it
        uno::Reference< uno::XInterface > xCFG( xConfigProvider->createInstanceWithArguments(
                    ::rtl::OUString::createFromAscii("com.sun.star.configuration.ConfigurationAccess"),
                    lParams) );

        uno::Reference< container::XNameAccess > xDirectAccess(xCFG, uno::UNO_QUERY);
        uno::Any aRet = xDirectAccess->getByName(::rtl::OUString::createFromAscii("ooSetupExtension"));

        aRet >>= setupextension;
    }
    catch ( uno::Exception& )
    {
    }

	rtl::OUString productversion(
        setupversion +
		rtl::OUString::createFromAscii( " " ) +
		setupextension );

    uno::Sequence< rtl::OUString > aImagesZipPaths( 2 );
    xHierAccess = getHierAccess( sProvider,	 "org.openoffice.Office.Common" );

    rtl::OUString aPath( getKey( xHierAccess, "Path/Current/UserConfig" ) );
    subst( aPath );
    aImagesZipPaths[ 0 ] = aPath;

	aPath = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("$OOO_BASE_DIR/share/config"));
	rtl::Bootstrap::expandMacros(aPath);
    aImagesZipPaths[ 1 ] = aPath;

	uno::Reference< uno::XComponentContext > xContext;
	uno::Reference< beans::XPropertySet > xProps( m_xSMgr, uno::UNO_QUERY );
    OSL_ASSERT( xProps.is() );
    if (xProps.is())
    {
        xProps->getPropertyValue(
			::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) >>= xContext;
        OSL_ASSERT( xContext.is() );
    }

    sal_Bool showBasic = getBooleanKey(xHierAccess,"Help/ShowBasic");
    m_pDatabases = new Databases( showBasic,
								  instPath,
								  aImagesZipPaths,
								  productname,
								  productversion,
								  stylesheet,
								  xContext );
}

uno::Reference< lang::XMultiServiceFactory >
ContentProvider::getConfiguration() const
{
    uno::Reference< lang::XMultiServiceFactory > sProvider;
	if( m_xSMgr.is() )
	{
		try
		{
			rtl::OUString sProviderService =
				rtl::OUString::createFromAscii(
					"com.sun.star.configuration.ConfigurationProvider" );
			sProvider =
				uno::Reference< lang::XMultiServiceFactory >(
					m_xSMgr->createInstance( sProviderService ),
					uno::UNO_QUERY );
		}
		catch( const uno::Exception& )
		{
            OSL_ENSURE( sProvider.is(), "can't instantiate configuration" );
		}
	}

	return sProvider;
}

uno::Reference< container::XHierarchicalNameAccess >
ContentProvider::getHierAccess(
    const uno::Reference< lang::XMultiServiceFactory >& sProvider,
    const char* file ) const
{
	uno::Reference< container::XHierarchicalNameAccess > xHierAccess;

	if( sProvider.is() )
	{
		uno::Sequence< uno::Any > seq( 1 );
		rtl::OUString sReaderService(
			rtl::OUString::createFromAscii(
                "com.sun.star.configuration.ConfigurationAccess" ) );

		seq[ 0 ] <<= rtl::OUString::createFromAscii( file );

		try
		{
			xHierAccess =
				uno::Reference< container::XHierarchicalNameAccess >(
                    sProvider->createInstanceWithArguments(
                        sReaderService, seq ),
                    uno::UNO_QUERY );
		}
		catch( const uno::Exception& )
		{
		}
	}
	return xHierAccess;
}



rtl::OUString
ContentProvider::getKey(
    const uno::Reference< container::XHierarchicalNameAccess >& xHierAccess,
    const char* key ) const
{
    rtl::OUString instPath;
	if( xHierAccess.is() )
	{
		uno::Any aAny;
		try
		{
			aAny =
				xHierAccess->getByHierarchicalName(
					rtl::OUString::createFromAscii( key ) );
		}
		catch( const container::NoSuchElementException& )
		{
		}
		aAny >>= instPath;
	}
	return instPath;
}

sal_Bool
ContentProvider::getBooleanKey(
    const uno::Reference< container::XHierarchicalNameAccess >& xHierAccess,
    const char* key ) const
{
  sal_Bool ret = sal_False;
  if( xHierAccess.is() )
  {
	  uno::Any aAny;
	  try
      {
		  aAny =
			xHierAccess->getByHierarchicalName(
                rtl::OUString::createFromAscii( key ) );
      }
	  catch( const container::NoSuchElementException& )
      {
      }
	  aAny >>= ret;
  }
  return ret;
}

void ContentProvider::subst( rtl::OUString& instpath ) const
{
	uno::Reference< frame::XConfigManager > xCfgMgr;
	if( m_xSMgr.is() )
	{
		try
		{
			xCfgMgr =
				uno::Reference< frame::XConfigManager >(
					m_xSMgr->createInstance(
                        rtl::OUString::createFromAscii(
                            "com.sun.star.config.SpecialConfigManager" ) ),
					uno::UNO_QUERY );
		}
		catch( const uno::Exception&)
		{
			OSL_ENSURE( xCfgMgr.is(),
                        "can't instantiate the special config manager " );
		}
    }

	OSL_ENSURE( xCfgMgr.is(), "specialconfigmanager not found\n" );

	if( xCfgMgr.is() )
        instpath = xCfgMgr->substituteVariables( instpath );
}
