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



#include "precompiled_vcl.hxx"

#include "vcl/wpropset.hxx"
#include "vcl/window.hxx"
#include "vcl/vclevent.hxx"

#include "svdata.hxx"

#include "com/sun/star/lang/XMultiServiceFactory.hpp"
#include "com/sun/star/beans/PropertyValue.hpp"
#include "com/sun/star/beans/PropertyAttribute.hpp"
#include "com/sun/star/beans/XPropertySet.hpp"
#include "com/sun/star/beans/XPropertyContainer.hpp"
#include "com/sun/star/beans/XPropertyAccess.hpp"

#include "cppuhelper/basemutex.hxx"
#include "cppuhelper/compbase1.hxx"

#include <map>

using namespace vcl;
using namespace com::sun::star;

/*

TODO:
- release solarmutex during outside UNO calls
- in ChildEventListener protect against reentry by using PostUserEvent

*/

class vcl::WindowPropertySetListener :
    public cppu::BaseMutex,
    public cppu::WeakComponentImplHelper1< com::sun::star::beans::XPropertyChangeListener >,
    private boost::noncopyable
{
    WindowPropertySet*      mpParent;
    bool                    mbSuspended;
public:
    WindowPropertySetListener( WindowPropertySet* pParent )
    : cppu::WeakComponentImplHelper1< com::sun::star::beans::XPropertyChangeListener >( m_aMutex )
    , mpParent( pParent )
    , mbSuspended( false )
    {}
    
    virtual ~WindowPropertySetListener()
    {
    }
    
    using cppu::WeakComponentImplHelperBase::disposing;
    virtual void SAL_CALL disposing( const lang::EventObject& ) throw()
    {
    }
    
    virtual void SAL_CALL propertyChange( const beans::PropertyChangeEvent& i_rEvent ) throw()
    {
        if( ! mbSuspended )
            mpParent->propertyChange( i_rEvent );
    }
    
    void suspend( bool i_bSuspended )
    {
        mbSuspended = i_bSuspended;
    }
};

class vcl::WindowPropertySetData
{
public:
    
    struct PropertyMapEntry
    {
        Window*                                 mpWindow;
        boost::shared_ptr<WindowArranger>       mpLayout;
        uno::Sequence< beans::PropertyValue >   maSavedValues;
        
        PropertyMapEntry( Window* i_pWindow = NULL,
                         const boost::shared_ptr<WindowArranger>& i_pLayout = boost::shared_ptr<WindowArranger>() )
        : mpWindow( i_pWindow )
        , mpLayout( i_pLayout )
        {}
        
        uno::Sequence< beans::PropertyValue > getProperties() const
        {
            if( mpWindow )
                return mpWindow->getProperties();
            else if( mpLayout.get() )
                return mpLayout->getProperties();
            return uno::Sequence< beans::PropertyValue >();
        }

        void setProperties( const uno::Sequence< beans::PropertyValue >& i_rProps ) const
        {
            if( mpWindow )
                mpWindow->setProperties( i_rProps );
            else if( mpLayout.get() )
                mpLayout->setProperties( i_rProps );
        }
    };
    
    Window*                                                         mpTopWindow;
    bool                                                            mbOwner;
    std::map< rtl::OUString, PropertyMapEntry >                     maProperties;
    uno::Reference< beans::XPropertySet >                           mxPropSet;
    uno::Reference< beans::XPropertyAccess >                        mxPropSetAccess;
    uno::Reference< beans::XPropertyChangeListener >                mxListener;
    vcl::WindowPropertySetListener*                                 mpListener;
    
    WindowPropertySetData()
    : mpTopWindow( NULL )
    , mbOwner( false )
    , mpListener( NULL )
    {}
    
    ~WindowPropertySetData()
    {
        // release layouters, possibly interface properties before destroying
        // the involved parent to be on the safe side
        maProperties.clear();
        if( mbOwner )
            delete mpTopWindow;
    }
};

static rtl::OUString getIdentifiedPropertyName( const rtl::OUString& i_rIdentifier, const rtl::OUString& i_rName )
{
    rtl::OUStringBuffer aBuf( i_rIdentifier.getLength() + 1 + i_rName.getLength() );
    aBuf.append( i_rIdentifier );
    aBuf.append( sal_Unicode( '#' ) );
    aBuf.append( i_rName );
    return aBuf.makeStringAndClear();
}

static void spliceIdentifiedPropertyName( const rtl::OUString& i_rIdentifiedPropName,
                                          rtl::OUString& o_rIdentifier,
                                          rtl::OUString& o_rPropName )
{
    sal_Int32 nIndex = 0;
    o_rIdentifier = i_rIdentifiedPropName.getToken( 0, sal_Unicode( '#' ), nIndex );
    if( nIndex != -1 )
        o_rPropName = i_rIdentifiedPropName.copy( nIndex );
    else
        o_rPropName = rtl::OUString();
}

WindowPropertySet::WindowPropertySet( Window* i_pTopWindow, bool i_bTakeOwnership )
: mpImpl( new vcl::WindowPropertySetData )
{
    mpImpl->mpTopWindow = i_pTopWindow;
    mpImpl->mbOwner = i_bTakeOwnership;
    
    mpImpl->mpTopWindow->AddChildEventListener( LINK( this, WindowPropertySet, ChildEventListener ) );
    
    mpImpl->mxPropSet = uno::Reference< beans::XPropertySet >(
        ImplGetSVData()->maAppData.mxMSF->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.beans.PropertyBag" ) ) ),
        uno::UNO_QUERY );
    OSL_ENSURE( mpImpl->mxPropSet.is(), "could not create instance of com.sun.star.beans.PropertyBag" );
    mpImpl->mxPropSetAccess = uno::Reference< beans::XPropertyAccess >( mpImpl->mxPropSet, uno::UNO_QUERY );
    OSL_ENSURE( mpImpl->mxPropSet.is(), "could not query XPropertyAccess interface" );
    if( ! mpImpl->mxPropSetAccess.is() )
        mpImpl->mxPropSet.clear();
    
    addWindowToSet( i_pTopWindow );
    
    setupProperties();
    
    if( mpImpl->mxPropSet.is() )
    {
        mpImpl->mxListener.set( mpImpl->mpListener = new WindowPropertySetListener( this ) );
    }
}

WindowPropertySet::~WindowPropertySet()
{
    mpImpl->mpTopWindow->RemoveChildEventListener( LINK( this, WindowPropertySet, ChildEventListener ) );

    delete mpImpl;
    mpImpl = NULL;
}

uno::Reference< beans::XPropertySet > WindowPropertySet::getPropertySet() const
{
    return mpImpl->mxPropSet;
}

void WindowPropertySet::addLayoutToSet( const boost::shared_ptr< WindowArranger >& i_pLayout )
{
    if( i_pLayout.get() )
    {
        if( i_pLayout->getIdentifier().getLength() )
        {
            WindowPropertySetData::PropertyMapEntry& rEntry = mpImpl->maProperties[ i_pLayout->getIdentifier() ];
            OSL_ENSURE( rEntry.mpWindow == 0 && rEntry.mpLayout.get() == 0, "inserted layout has duplicate name" );
            rEntry.mpWindow = NULL;
            rEntry.mpLayout = i_pLayout;
            rEntry.maSavedValues = i_pLayout->getProperties();
        }
        // insert child layouts
        size_t nChildren = i_pLayout->countElements();
        for( size_t i = 0; i < nChildren; i++ )
            addLayoutToSet( i_pLayout->getChild( i ) );
    }
}

void WindowPropertySet::addWindowToSet( Window* i_pWindow )
{
    if( i_pWindow->getIdentifier().getLength() ) // no name, no properties
    {
        WindowPropertySetData::PropertyMapEntry& rEntry = mpImpl->maProperties[ i_pWindow->getIdentifier() ];
        OSL_ENSURE( rEntry.mpWindow == 0 && rEntry.mpLayout.get() == 0, "inserted window has duplicate name" );
        rEntry.mpWindow = i_pWindow;
        rEntry.mpLayout.reset();
        rEntry.maSavedValues = i_pWindow->getProperties();
    }
    addLayoutToSet( i_pWindow->getLayout() );
    
    Window* pWin = i_pWindow->GetWindow( WINDOW_FIRSTCHILD );
    while( pWin )
    {
        addWindowToSet( pWin );
        pWin = pWin->GetWindow( WINDOW_NEXT );
    }
}

void WindowPropertySet::setupProperties()
{
    uno::Reference< beans::XPropertyContainer > xCont( mpImpl->mxPropSet, uno::UNO_QUERY );
    OSL_ENSURE( xCont.is(), "could not get XPropertyContainer interface" );
    if( ! xCont.is() )
        return;
    
    for( std::map< rtl::OUString, WindowPropertySetData::PropertyMapEntry >::iterator it
         = mpImpl->maProperties.begin(); it != mpImpl->maProperties.end(); ++it )
    {
        uno::Sequence< beans::PropertyValue > aOutsideValues( it->second.maSavedValues );
        beans::PropertyValue* pVal = aOutsideValues.getArray();
        for( sal_Int32 i = 0; i <  aOutsideValues.getLength(); i++ )
        {
            pVal[i].Name = getIdentifiedPropertyName( it->first, pVal[i].Name );
            xCont->addProperty( pVal[i].Name,
                                beans::PropertyAttribute::BOUND | beans:: PropertyAttribute::CONSTRAINED,
                                pVal[i].Value
                                );
        }
    }
}

void WindowPropertySet::propertyChange( const beans::PropertyChangeEvent& i_rEvent )
{
    rtl::OUString aIdentifier, aProperty;
    spliceIdentifiedPropertyName( i_rEvent.PropertyName, aIdentifier, aProperty );
    std::map< rtl::OUString, WindowPropertySetData::PropertyMapEntry >::iterator it =
        mpImpl->maProperties.find( aIdentifier );
    if( it != mpImpl->maProperties.end() )
    {
        uno::Sequence< beans::PropertyValue > aSet( 1 );
        aSet[0].Name  = aProperty;
        aSet[0].Value = i_rEvent.NewValue;
        it->second.setProperties( aSet );
    }
}

IMPL_LINK( vcl::WindowPropertySet, ChildEventListener, VclWindowEvent*, pEvent )
{
    // find window in our properties
    std::map< rtl::OUString, WindowPropertySetData::PropertyMapEntry >::iterator it
    = mpImpl->maProperties.find( pEvent->GetWindow()->getIdentifier() );
    if( it != mpImpl->maProperties.end() ) // this is valid, some unnamed child may have sent an event
    {
        sal_uLong nId = pEvent->GetId();
        // check if anything interesting happened
        if(
           // general windowy things
           nId == VCLEVENT_WINDOW_SHOW                  ||
           nId == VCLEVENT_WINDOW_HIDE                  ||
           nId == VCLEVENT_WINDOW_ENABLED               ||
           nId == VCLEVENT_WINDOW_DISABLED              ||
           // button thingies
           nId == VCLEVENT_BUTTON_CLICK                 ||
           nId == VCLEVENT_PUSHBUTTON_TOGGLE            ||
           nId == VCLEVENT_RADIOBUTTON_TOGGLE           ||
           nId == VCLEVENT_CHECKBOX_TOGGLE              ||
           // listbox
           nId == VCLEVENT_LISTBOX_SELECT               ||
           // edit
           nId == VCLEVENT_EDIT_MODIFY
           )
        {
            WindowPropertySetData::PropertyMapEntry& rEntry = it->second;
            // collect changes
            uno::Sequence< beans::PropertyValue > aNewProps( rEntry.getProperties() );
            uno::Sequence< beans::PropertyValue > aNewPropsOut( aNewProps );
            
            // translate to identified properties
            beans::PropertyValue* pValues = aNewPropsOut.getArray();
            for( sal_Int32 i = 0; i < aNewPropsOut.getLength(); i++ )
                pValues[i].Name = getIdentifiedPropertyName( it->first, pValues[i].Name );
            
            // broadcast changes
            bool bWasVeto = false;
            mpImpl->mpListener->suspend( true );
            try
            {
                mpImpl->mxPropSetAccess->setPropertyValues( aNewPropsOut );
            }
            catch( beans::PropertyVetoException& )
            {
                bWasVeto = true;
            }
            mpImpl->mpListener->suspend( false );
            
            if( ! bWasVeto ) // changes accepted ?
                rEntry.maSavedValues = rEntry.getProperties();
            else // no, reset
                rEntry.setProperties( rEntry.maSavedValues );
        }
    }
    
    return 0;
}
