/*************************************************************************
 *
 *  $RCSfile: ScriptInfo.cxx,v $
 *
 *  $Revision: 1.11 $
 *
 *  last change: $Author: dfoster $ $Date: 2002-11-06 16:26:24 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#include <cppuhelper/implementationentry.hxx>

#include <hash_map>

#include <osl/file.hxx>
#include <cppuhelper/implbase1.hxx>

#include <com/sun/star/beans/XPropertyContainer.hpp>
#include <com/sun/star/beans/PropertyAttribute.hpp>

#include <drafts/com/sun/star/script/framework/storage/XScriptStorageManager.hpp>

#include <util/util.hxx>
#include "ScriptInfo.hxx"

using namespace ::rtl;
using namespace com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::drafts::com::sun::star::script::framework;
using namespace ::drafts::com::sun::star::script::framework::storage;

namespace scripting_impl
{

typedef ::std::hash_map < ::rtl::OUString, css::uno::Any, ::rtl::OUStringHash,
    ::std::equal_to< ::rtl::OUString > > PropertySet_hash;

class PropertySetImpl : public ::cppu::WeakImplHelper1< css::beans::XPropertySet >
{

public:

    PropertySetImpl();
    ~PropertySetImpl();

// XPropertySet implementation
    virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
        getPropertySetInfo()
        throw ( css::uno::RuntimeException );
    virtual void SAL_CALL setPropertyValue( const ::rtl::OUString& aPropertyName,
        const css::uno::Any& aValue )
        throw ( css::beans::UnknownPropertyException,
            css::beans::PropertyVetoException,
            css::lang::IllegalArgumentException,
            css::lang::WrappedTargetException,
            css::uno::RuntimeException );
    virtual css::uno::Any SAL_CALL getPropertyValue( const ::rtl::OUString& PropertyName )
        throw ( css::beans::UnknownPropertyException,
            css::lang::WrappedTargetException,
            css::uno::RuntimeException );
    virtual void SAL_CALL addPropertyChangeListener( const ::rtl::OUString& aPropertyName,
        const css::uno::Reference< css::beans::XPropertyChangeListener >& xListener )
        throw ( css::beans::UnknownPropertyException,
            css::lang::WrappedTargetException,
            css::uno::RuntimeException );
    virtual void SAL_CALL removePropertyChangeListener(
        const ::rtl::OUString& aPropertyName,
        const css::uno::Reference< css::beans::XPropertyChangeListener >& aListener )
        throw ( css::beans::UnknownPropertyException,
            css::lang::WrappedTargetException,
            css::uno::RuntimeException );
    virtual void SAL_CALL addVetoableChangeListener(
        const ::rtl::OUString& PropertyName,
        const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener )
        throw ( css::beans::UnknownPropertyException,
            css::lang::WrappedTargetException,
            css::uno::RuntimeException );
    virtual void SAL_CALL removeVetoableChangeListener(
        const ::rtl::OUString& PropertyName,
        const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener )
        throw ( css::beans::UnknownPropertyException,
            css::lang::WrappedTargetException,
            css::uno::RuntimeException );

private:
    friend class ScriptInfo;

    css::uno::Reference< css::uno::XComponentContext > m_xContext;
    void PropertySetImpl::privateSetPropertyValue( const ::rtl::OUString& aPropertyName, const Any& aValue )
    throw ( beans::UnknownPropertyException, beans::PropertyVetoException,
            lang::IllegalArgumentException, lang::WrappedTargetException,
            RuntimeException );

    osl::Mutex m_mutex;
    PropertySet_hash m_propertyMap;
};

PropertySetImpl::PropertySetImpl()
{
   OSL_TRACE( "<PropertySetImpl ctor called\n" );
}

PropertySetImpl::~PropertySetImpl()
{
    OSL_TRACE( "<PropertySetImpl dtor called\n>" );
}

Reference< beans::XPropertySetInfo > SAL_CALL PropertySetImpl::getPropertySetInfo( )
    throw ( RuntimeException )
{
    return Reference< beans::XPropertySetInfo > (); // Not supported
}

void SAL_CALL PropertySetImpl::setPropertyValue( const ::rtl::OUString& aPropertyName,
    const Any& aValue )
    throw ( beans::UnknownPropertyException, beans::PropertyVetoException,
            lang::IllegalArgumentException, lang::WrappedTargetException,
            RuntimeException )
{
    throw RuntimeException(
        OUSTR( "PropertySetImpl::setPropertyValue: method not supported. Read-only PropertySet" ),
        Reference< XInterface >() );
}

void PropertySetImpl::privateSetPropertyValue( const ::rtl::OUString& aPropertyName,
    const Any& aValue )
    throw ( beans::UnknownPropertyException, beans::PropertyVetoException,
            lang::IllegalArgumentException, lang::WrappedTargetException,
            RuntimeException )
{
    ::osl::Guard< osl::Mutex > aGuard( m_mutex );
    m_propertyMap[ aPropertyName ] = aValue;
}

//*************************************************************************
Any SAL_CALL PropertySetImpl::getPropertyValue( const ::rtl::OUString& PropertyName )
    throw ( beans::UnknownPropertyException,
            lang::WrappedTargetException, RuntimeException )
{
    if ( m_propertyMap.find( PropertyName ) == m_propertyMap.end() )
    {
        throw RuntimeException(

            OUSTR( "PropertySetImpl::getPropertyValue: invalid PropertyName ").concat(
                PropertyName),
            Reference< XInterface >() );
    }

    ::osl::Guard< osl::Mutex > aGuard( m_mutex );
    Any returnValue = m_propertyMap[ PropertyName ];

    return returnValue;
}

//*************************************************************************
void SAL_CALL PropertySetImpl::addPropertyChangeListener(
    const ::rtl::OUString& aPropertyName,
    const Reference< beans::XPropertyChangeListener >& xListener )
    throw ( beans::UnknownPropertyException, lang::WrappedTargetException,
            RuntimeException )
{
    throw RuntimeException(
        OUSTR( "PropertySetImpl::addPropertyChangeListener: method not supported" ),
        Reference< XInterface >() );
}

//*************************************************************************
void SAL_CALL PropertySetImpl::removePropertyChangeListener(
    const ::rtl::OUString& aPropertyName,
    const Reference< beans::XPropertyChangeListener >& aListener )
    throw ( beans::UnknownPropertyException, lang::WrappedTargetException,
            RuntimeException )
{
    throw RuntimeException(
        OUSTR( "PropertySetImpl::removePropertyChangeListener: method not supported" ),
        Reference< XInterface >() );
}

//*************************************************************************
void SAL_CALL PropertySetImpl::addVetoableChangeListener(
    const ::rtl::OUString& PropertyName,
    const Reference< beans::XVetoableChangeListener >& aListener )
    throw ( beans::UnknownPropertyException, lang::WrappedTargetException,
            RuntimeException )
{
    throw RuntimeException(
        OUSTR( "PropertySetImpl::addVetoableChangeListener: method not supported" ),
        Reference< XInterface >() );
}

//*************************************************************************
void SAL_CALL PropertySetImpl::removeVetoableChangeListener(
    const ::rtl::OUString& PropertyName,
    const Reference< beans::XVetoableChangeListener >& aListener )
    throw ( beans::UnknownPropertyException, lang::WrappedTargetException,
            RuntimeException )
{
    throw RuntimeException(
        OUSTR( "PropertySetImpl::removeVetoableChangeListener: method not supported" ),
        Reference< XInterface >() );
}


//*************************************************************************
ScriptInfo::ScriptInfo( const ScriptData & scriptData, sal_Int32 storageID )
        : m_scriptData( scriptData ), m_storageID( storageID )
{
    OSL_TRACE( "< ++++++ ScriptInfo ctor called >\n" );
    OSL_TRACE( "< ++++++ parcelURI=%s>\n",::rtl::OUStringToOString(m_scriptData.parcelURI , RTL_TEXTENCODING_ASCII_US ).pData->buffer );
}
//*************************************************************************
ScriptInfo::~ScriptInfo()
{
    OSL_TRACE( "< ScriptInfo dtor called >\n" );
}
//*************************************************************************
OUString SAL_CALL ScriptInfo::getLogicalName(  ) throw ( RuntimeException )
{
    OSL_TRACE( "ScriptInfo::getLogicalName() " );
    return m_scriptData.logicalname;
}

//*************************************************************************
OUString SAL_CALL ScriptInfo::getDescription(  ) throw ( RuntimeException )
{
    OUString rs_desc;
    // TDB need to determine locale here, hardcoded at the moment
    // to english

    OUString localeLang = OUString::createFromAscii( "en" );
    strpair_map::const_iterator str_it =
        m_scriptData.locales.find( localeLang );

    if( str_it == m_scriptData.locales.end() )
    {
        OSL_TRACE( "No description set in meta-data" );
        return rs_desc;
    }
    rs_desc = str_it->second.second;
    return rs_desc;
}

//*************************************************************************
OUString SAL_CALL ScriptInfo::getLanguage(  ) throw ( RuntimeException )
{
    OSL_TRACE( "ScriptInfo::getLanguage() " );
    return m_scriptData.language;
}

//*************************************************************************
OUString SAL_CALL ScriptInfo::getFunctionName(  ) throw ( RuntimeException )
{
    OSL_TRACE( "ScriptInfo::getFunctionName() " );
    return m_scriptData.functionname;
}

//*************************************************************************
OUString SAL_CALL ScriptInfo::getParcelURI(  ) throw ( RuntimeException )
{
    return m_scriptData.parcelURI;
}

//*************************************************************************
Reference< beans::XPropertySet > SAL_CALL ScriptInfo::getLanguageProperties(  )
    throw ( RuntimeException )
{
    PropertySetImpl* propSetImpl = new PropertySetImpl();
    Reference< beans::XPropertySet > xPropSet = propSetImpl;

    props_vec::const_iterator pv_it = m_scriptData.languagedepprops.begin();
    props_vec::const_iterator pv_itend = m_scriptData.languagedepprops.end();

    for( ; pv_it != pv_itend; ++pv_it )
    {
        try
        {
            propSetImpl->privateSetPropertyValue( pv_it->first, makeAny( pv_it->second ) );
        }
        catch( Exception& e )
        {
            OUString msg = OUSTR(
                "ScriptInfo::getLanguage caught exception while setting property," );
            msg = msg.concat( OUSTR( " PropertryName: " ) ).concat( pv_it->first );
            msg = msg.concat( OUSTR( " \nException message is: " ) );
            msg = msg.concat( e.Message );
            throw RuntimeException( msg , Reference< XInterface >() );
        }
    }

    return xPropSet;
}
//*************************************************************************
css::uno::Sequence< ::rtl::OUString > SAL_CALL ScriptInfo::getFileSetNames()
throw ( css::uno::RuntimeException )
{
    OSL_TRACE("ScriptInfo::getFileSetNames");
    Sequence< OUString > results;
    filesets_map::iterator fsm_it = m_scriptData.filesets.begin();
    filesets_map::iterator fsm_itend = m_scriptData.filesets.end();
    if( fsm_it == fsm_itend )
    {
        OSL_TRACE( "ScriptInfo::getFileSetNames: no filesets" );
        return results;
    }
    results.realloc( m_scriptData.filesets.size() );
    for ( sal_Int32 count = 0; fsm_it != fsm_itend; ++fsm_it )
    {
        OUString fileSetName = fsm_it->first;
        OSL_TRACE( "ScriptInfo::getFileSetNames: adding name %s",
            ::rtl::OUStringToOString( fileSetName,
                RTL_TEXTENCODING_ASCII_US ).pData->buffer );
        results[ count++ ] = fileSetName;
    }
    return results;
}
//*************************************************************************
css::uno::Sequence< ::rtl::OUString > SAL_CALL
ScriptInfo::getFilesInFileSet( const ::rtl::OUString & fileSetName )
throw ( css::uno::RuntimeException )
{
    Sequence< OUString > results;
    filesets_map::iterator fsm_it = m_scriptData.filesets.find( fileSetName );
    filesets_map::iterator fsm_itend = m_scriptData.filesets.end();
    if( fsm_it == fsm_itend )
    {
        OSL_TRACE( "ScriptInfo::getFilesInFileSet: no fileset named %s",
            ::rtl::OUStringToOString( fileSetName,
                RTL_TEXTENCODING_ASCII_US ).pData->buffer );
        return results;
    }

    strpairvec_map files = fsm_it->second.second;
    strpairvec_map::iterator spvm_it = files.begin();
    strpairvec_map::iterator spvm_itend = files.end();
    if( spvm_it == spvm_itend )
    {
        OSL_TRACE( "ScriptInfo::getFilesInFileSet: no files in fileset %s",
            ::rtl::OUStringToOString( fileSetName,
                RTL_TEXTENCODING_ASCII_US ).pData->buffer );
        return results;
    }
    results.realloc( files.size() );
    for( sal_Int32 count = 0; spvm_it != spvm_itend ; ++spvm_it )
    {
        OUString fileName = spvm_it->first;
        OSL_TRACE( "ScriptInfo::getFilesInFileSet: adding file %s",
            ::rtl::OUStringToOString( fileName,
                RTL_TEXTENCODING_ASCII_US ).pData->buffer );
        results[ count++ ] = fileName;
    }
    return results;
}
//*************************************************************************
}
