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

#include <ooo/vba/XCollection.hpp>
#include <com/sun/star/container/XEnumerationAccess.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>
#include <com/sun/star/script/XDefaultMethod.hpp>
#include <com/sun/star/container/XIndexAccess.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/container/XNamed.hpp>

#include <cppuhelper/implbase3.hxx>
#include <cppuhelper/implbase2.hxx>
#include <cppuhelper/implbase1.hxx>

#include "vbahelper/vbahelper.hxx"
#include "vbahelper/vbahelperinterface.hxx"

#include <vector>

// ============================================================================

typedef ::cppu::WeakImplHelper1< css::container::XEnumeration > EnumerationHelper_BASE;

// ============================================================================

/** A wrapper that holds a com.sun.star.container.XIndexAccess and provides a
    com.sun.star.container.XEnumeration.

    Can be used to provide an enumeration from an index container that contains
    completely constructed/initialized VBA implementation objects. CANNOT be
    used to provide an enumeration from an index container with other objects
    (e.g. UNO objects) where construction of the VBA objects is needed first.
 */
class VBAHELPER_DLLPUBLIC SimpleIndexAccessToEnumeration : public EnumerationHelper_BASE
{
public:
    explicit SimpleIndexAccessToEnumeration(
            const css::uno::Reference< css::container::XIndexAccess >& rxIndexAccess ) throw (css::uno::RuntimeException) :
        mxIndexAccess( rxIndexAccess ), mnIndex( 0 ) {}

    virtual sal_Bool SAL_CALL hasMoreElements() throw (css::uno::RuntimeException)
    {
        return mnIndex < mxIndexAccess->getCount();
    }

    virtual css::uno::Any SAL_CALL nextElement() throw (css::container::NoSuchElementException, css::lang::WrappedTargetException, css::uno::RuntimeException)
    {
        if( !hasMoreElements() )
            throw css::container::NoSuchElementException();
        return mxIndexAccess->getByIndex( mnIndex++ );
    }

private:
    css::uno::Reference< css::container::XIndexAccess > mxIndexAccess;
    sal_Int32 mnIndex;
};

// ============================================================================

/** A wrapper that holds a com.sun.star.container.XEnumeration or a
    com.sun.star.container.XIndexAccess and provides an enumeration of VBA objects.

    The method createCollectionObject() needs to be implemented by the derived
    class. This class can be used to convert an enumeration or an index container
    containing UNO objects to an enumeration providing the related VBA objects.
 */
class VBAHELPER_DLLPUBLIC SimpleEnumerationBase : public EnumerationHelper_BASE
{
public:
    explicit SimpleEnumerationBase(
            const css::uno::Reference< ov::XHelperInterface >& rxParent,
            const css::uno::Reference< css::uno::XComponentContext >& rxContext,
            const css::uno::Reference< css::container::XEnumeration >& rxEnumeration ) throw (css::uno::RuntimeException) :
        mxParent( rxParent ), mxContext( rxContext ), mxEnumeration( rxEnumeration ) {}

    explicit SimpleEnumerationBase(
            const css::uno::Reference< ov::XHelperInterface >& rxParent,
            const css::uno::Reference< css::uno::XComponentContext >& rxContext,
            const css::uno::Reference< css::container::XIndexAccess >& rxIndexAccess ) throw (css::uno::RuntimeException) :
        mxParent( rxParent ), mxContext( rxContext ), mxEnumeration( new SimpleIndexAccessToEnumeration( rxIndexAccess ) ) {}

    virtual sal_Bool SAL_CALL hasMoreElements() throw (css::uno::RuntimeException)
    {
        return mxEnumeration->hasMoreElements();
    }

    virtual css::uno::Any SAL_CALL nextElement() throw (css::container::NoSuchElementException, css::lang::WrappedTargetException, css::uno::RuntimeException)
    {
        return createCollectionObject( mxEnumeration->nextElement() );
    }

    /** Derived classes implement creation of a VBA implementation object from
        the passed container element. */
    virtual css::uno::Any createCollectionObject( const css::uno::Any& rSource ) = 0;

protected:
    css::uno::Reference< ov::XHelperInterface > mxParent;
    css::uno::Reference< css::uno::XComponentContext > mxContext;
    css::uno::Reference< css::container::XEnumeration > mxEnumeration;
};

// ============================================================================

// deprecated, use SimpleEnumerationBase instead!
class VBAHELPER_DLLPUBLIC EnumerationHelperImpl : public EnumerationHelper_BASE
{
protected:
	css::uno::WeakReference< ov::XHelperInterface > m_xParent;
	css::uno::Reference< css::uno::XComponentContext > m_xContext;
	css::uno::Reference< css::container::XEnumeration > m_xEnumeration;
public:

	EnumerationHelperImpl( const css::uno::Reference< ov::XHelperInterface >& xParent, const css::uno::Reference< css::uno::XComponentContext >& xContext, const css::uno::Reference< css::container::XEnumeration >& xEnumeration ) throw ( css::uno::RuntimeException ) : m_xParent( xParent ), m_xContext( xContext ),  m_xEnumeration( xEnumeration ) { }
	virtual ::sal_Bool SAL_CALL hasMoreElements(  ) throw (css::uno::RuntimeException) { return m_xEnumeration->hasMoreElements(); }
};

// a wrapper class for a providing a XIndexAccess, XNameAccess, XEnumerationAccess impl based on providing a vector of interfaces
// only requirement is the object needs to implement XName



typedef ::cppu::WeakImplHelper3< css::container::XNameAccess, css::container::XIndexAccess, css::container::XEnumerationAccess > XNamedCollectionHelper_BASE;

template< typename Ifc1 >
class XNamedObjectCollectionHelper : public XNamedCollectionHelper_BASE
{
public:
typedef std::vector< css::uno::Reference< Ifc1 > >  XNamedVec;
private:

	class XNamedEnumerationHelper : public EnumerationHelper_BASE
	{
		XNamedVec mXNamedVec;
		typename XNamedVec::iterator mIt;
	public:
	        XNamedEnumerationHelper( const XNamedVec& sMap ) : mXNamedVec( sMap ), mIt( mXNamedVec.begin() ) {}
	
	        virtual ::sal_Bool SAL_CALL hasMoreElements(  ) throw (css::uno::RuntimeException)
	        {
			return ( mIt != mXNamedVec.end() );
	        }
	
	        virtual css::uno::Any SAL_CALL nextElement(  ) throw (css::container::NoSuchElementException, css::lang::WrappedTargetException, css::uno::RuntimeException)
	        {
	                if ( hasMoreElements() )
				return css::uno::makeAny( *mIt++ );
	                throw css::container::NoSuchElementException();
	        }
	};

protected:
	XNamedVec mXNamedVec;
	typename XNamedVec::iterator cachePos;
public:
	XNamedObjectCollectionHelper( const XNamedVec& sMap ) : mXNamedVec( sMap ), cachePos(mXNamedVec.begin()) {}
	// XElementAccess
	virtual css::uno::Type SAL_CALL getElementType(  ) throw (css::uno::RuntimeException) { return  Ifc1::static_type(0); }
	virtual ::sal_Bool SAL_CALL hasElements(  ) throw (css::uno::RuntimeException) { return ( mXNamedVec.size() > 0 ); }
	// XNameAcess 
	virtual css::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName ) throw (css::container::NoSuchElementException, css::lang::WrappedTargetException, css::uno::RuntimeException)
	{
		if ( !hasByName(aName) )
			throw css::container::NoSuchElementException();
		return css::uno::makeAny( *cachePos );
	}
	virtual css::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames(  ) throw (css::uno::RuntimeException)
	{
		css::uno::Sequence< rtl::OUString > sNames( mXNamedVec.size() );
		rtl::OUString* pString = sNames.getArray();
		typename XNamedVec::iterator it = mXNamedVec.begin();
		typename XNamedVec::iterator it_end = mXNamedVec.end();

		for ( ; it != it_end; ++it, ++pString )
		{
			css::uno::Reference< css::container::XNamed > xName( *it, css::uno::UNO_QUERY_THROW );	
			*pString = xName->getName();
		}
		return sNames;
	}
	virtual ::sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) throw (css::uno::RuntimeException)
	{
		cachePos = mXNamedVec.begin();
		typename XNamedVec::iterator it_end = mXNamedVec.end();
		for ( ; cachePos != it_end; ++cachePos )
		{
			css::uno::Reference< css::container::XNamed > xName( *cachePos, css::uno::UNO_QUERY_THROW );	
			if ( aName.equals( xName->getName() ) )
				break;
		}
		return ( cachePos != it_end );
	}

	// XElementAccess
	virtual ::sal_Int32 SAL_CALL getCount(  ) throw (css::uno::RuntimeException) { return mXNamedVec.size(); }	
	virtual css::uno::Any SAL_CALL getByIndex( ::sal_Int32 Index ) throw (css::lang::IndexOutOfBoundsException, css::lang::WrappedTargetException, css::uno::RuntimeException )
	{
		if ( Index < 0 || Index >= getCount() )
			throw css::lang::IndexOutOfBoundsException();
	
		return css::uno::makeAny( mXNamedVec[ Index ] );

	}
	// XEnumerationAccess
	virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createEnumeration(  ) throw (css::uno::RuntimeException)
	{
		return new XNamedEnumerationHelper( mXNamedVec );
	}
};

// including a HelperInterface implementation
template< typename Ifc1 >
class ScVbaCollectionBase : public InheritedHelperInterfaceImpl< Ifc1 >
{
typedef InheritedHelperInterfaceImpl< Ifc1 > BaseColBase;
protected:
	css::uno::Reference< css::container::XIndexAccess > m_xIndexAccess;
	css::uno::Reference< css::container::XNameAccess > m_xNameAccess;

	virtual css::uno::Any getItemByStringIndex( const rtl::OUString& sIndex ) throw (css::uno::RuntimeException)
	{
		if ( !m_xNameAccess.is() )
			throw css::uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ScVbaCollectionBase string index access not supported by this object") ), css::uno::Reference< css::uno::XInterface >() );
	
		return createCollectionObject( m_xNameAccess->getByName( sIndex ) );	
	}		

	virtual css::uno::Any getItemByIntIndex( const sal_Int32 nIndex ) throw (css::uno::RuntimeException)
	{
		if ( !m_xIndexAccess.is() )
			throw css::uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ScVbaCollectionBase numeric index access not supported by this object") ), css::uno::Reference< css::uno::XInterface >() );
		if ( nIndex <= 0 )
		{
			throw  css::lang::IndexOutOfBoundsException( 
				::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 
				"index is 0 or negative" ) ), 
				css::uno::Reference< css::uno::XInterface >() );
		}
		// need to adjust for vba index ( for which first element is 1 )
		return createCollectionObject( m_xIndexAccess->getByIndex( nIndex - 1 ) );		
	}

    virtual void UpdateCollectionIndex( const css::uno::Reference< css::container::XIndexAccess >& xIndexAccess )
    {
        css::uno::Reference< css::container::XNameAccess > xNameAccess( xIndexAccess, css::uno::UNO_QUERY_THROW );
        m_xIndexAccess = xIndexAccess;
        m_xNameAccess = xNameAccess;
    }

public:
	ScVbaCollectionBase( const css::uno::Reference< ov::XHelperInterface >& xParent,   const css::uno::Reference< css::uno::XComponentContext >& xContext, const css::uno::Reference< css::container::XIndexAccess >& xIndexAccess ) : BaseColBase( xParent, xContext ), m_xIndexAccess( xIndexAccess ){ m_xNameAccess.set(m_xIndexAccess, css::uno::UNO_QUERY); }
	//XCollection
	virtual ::sal_Int32 SAL_CALL getCount() throw (css::uno::RuntimeException)
	{
		return m_xIndexAccess->getCount();
	}

	virtual css::uno::Any SAL_CALL Item( const css::uno::Any& Index1, const css::uno::Any& /*not processed in this base class*/ ) throw (css::uno::RuntimeException)
	{
		if ( Index1.getValueTypeClass() != css::uno::TypeClass_STRING )
		{
			sal_Int32 nIndex = 0;
	
			if ( ( Index1 >>= nIndex ) != sal_True )
			{
				rtl::OUString message;
				message = rtl::OUString::createFromAscii(
					"Couldn't convert index to Int32");
				throw  css::lang::IndexOutOfBoundsException( message,
					css::uno::Reference< css::uno::XInterface >() );
			}
			return 	getItemByIntIndex( nIndex );
		}
		rtl::OUString aStringSheet;

		Index1 >>= aStringSheet;
		return getItemByStringIndex( aStringSheet );	
	}
	// XDefaultMethod
	::rtl::OUString SAL_CALL getDefaultMethodName(  ) throw (css::uno::RuntimeException)
	{
		const static rtl::OUString sName( RTL_CONSTASCII_USTRINGPARAM("Item") );
		return sName;
	}
	// XEnumerationAccess
	virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createEnumeration() throw (css::uno::RuntimeException) = 0;	

	// XElementAccess
	virtual css::uno::Type SAL_CALL getElementType() throw (css::uno::RuntimeException) = 0;
	// XElementAccess
	virtual ::sal_Bool SAL_CALL hasElements() throw (css::uno::RuntimeException)
	{
		return ( m_xIndexAccess->getCount() > 0 );
	}
	virtual css::uno::Any createCollectionObject( const css::uno::Any& aSource ) = 0;
	
};

typedef ::cppu::WeakImplHelper1<ov::XCollection> XCollection_InterfacesBASE;

typedef ScVbaCollectionBase< XCollection_InterfacesBASE > CollImplBase1;
// compatible with the old collections ( pre XHelperInterface base class ) ( some internal objects still use this )
class VBAHELPER_DLLPUBLIC ScVbaCollectionBaseImpl : public CollImplBase1
{
public:
	ScVbaCollectionBaseImpl( const css::uno::Reference< ov::XHelperInterface > xParent, const css::uno::Reference< css::uno::XComponentContext >& xContext, const css::uno::Reference< css::container::XIndexAccess >& xIndexAccess ) throw( css::uno::RuntimeException ) : CollImplBase1( xParent, xContext, xIndexAccess){}

};

template <typename Ifc> // where Ifc must implement XCollectionTest
class CollTestImplHelper :  public ScVbaCollectionBase< ::cppu::WeakImplHelper1< Ifc > >
{
typedef ScVbaCollectionBase< ::cppu::WeakImplHelper1< Ifc >  > ImplBase1;

public:
	CollTestImplHelper( const css::uno::Reference< ov::XHelperInterface >& xParent, const css::uno::Reference< css::uno::XComponentContext >& xContext,  const css::uno::Reference< css::container::XIndexAccess >& xIndexAccess ) throw( css::uno::RuntimeException ) : ImplBase1( xParent, xContext, xIndexAccess ) {}
};


#endif //SC_VBA_COLLECTION_IMPL_HXX
