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

#include <sfx2/docinf.hxx>
#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/document/XDocumentProperties.hpp>
#include <com/sun/star/uno/Exception.hpp>
#include <rtl/ustring.hxx>
#include <tools/debug.hxx>
#include <comphelper/string.hxx>
#include <sot/storage.hxx>
#include <vcl/gdimtf.hxx>
#include <vcl/dibtools.hxx>
#include "oleprops.hxx"

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

// stream names
#define STREAM_SUMMARYINFO      "\005SummaryInformation"
#define STREAM_DOCSUMMARYINFO   "\005DocumentSummaryInformation"

// usings
using namespace ::com::sun::star;


namespace sfx2 {

sal_uInt32 SFX2_DLLPUBLIC LoadOlePropertySet(
    uno::Reference< document::XDocumentProperties> i_xDocProps,
    SotStorage* i_pStorage )
{
    // *** global properties from stream "005SummaryInformation" ***

    // load the property set
    SfxOlePropertySet aGlobSet;
    ErrCode nGlobError = aGlobSet.LoadPropertySet(i_pStorage,
        String( RTL_CONSTASCII_USTRINGPARAM( STREAM_SUMMARYINFO ) ) );

    // global section
    SfxOleSectionRef xGlobSect = aGlobSet.GetSection( SECTION_GLOBAL );
    if( xGlobSect.get() )
    {
        // set supported properties
        String aStrValue;
        util::DateTime aDateTime;

        if( xGlobSect->GetStringValue( aStrValue, PROPID_TITLE ) )
            i_xDocProps->setTitle( aStrValue );
        if( xGlobSect->GetStringValue( aStrValue, PROPID_SUBJECT ) )
            i_xDocProps->setSubject( aStrValue );
        if( xGlobSect->GetStringValue( aStrValue, PROPID_KEYWORDS ) ) {
            i_xDocProps->setKeywords(
                ::comphelper::string::convertCommaSeparated(aStrValue) );
        }
        if( xGlobSect->GetStringValue( aStrValue, PROPID_TEMPLATE ) )
            i_xDocProps->setTemplateName( aStrValue );
        if( xGlobSect->GetStringValue( aStrValue, PROPID_COMMENTS ) )
            i_xDocProps->setDescription( aStrValue );

		util::DateTime aInvalid;
        if( xGlobSect->GetStringValue( aStrValue, PROPID_AUTHOR) )
			i_xDocProps->setAuthor( aStrValue );
		else
			i_xDocProps->setAuthor( ::rtl::OUString() );
        if( xGlobSect->GetFileTimeValue( aDateTime, PROPID_CREATED ) )
			i_xDocProps->setCreationDate( aDateTime );
		else
			i_xDocProps->setCreationDate( aInvalid );

        if( xGlobSect->GetStringValue( aStrValue, PROPID_LASTAUTHOR) )
			i_xDocProps->setModifiedBy( aStrValue );
		else
			i_xDocProps->setModifiedBy( ::rtl::OUString() );
        if( xGlobSect->GetFileTimeValue( aDateTime, PROPID_LASTSAVED ) )
			i_xDocProps->setModificationDate( aDateTime );
		else
			i_xDocProps->setModificationDate( aInvalid );

		i_xDocProps->setPrintedBy( ::rtl::OUString() );
        if( xGlobSect->GetFileTimeValue( aDateTime, PROPID_LASTPRINTED ) )
			i_xDocProps->setPrintDate( aDateTime );
		else
			i_xDocProps->setPrintDate( aInvalid );

        if( xGlobSect->GetStringValue( aStrValue, PROPID_REVNUMBER ) )
        {
            sal_Int16 nRevision = static_cast< sal_Int16 >( aStrValue.ToInt32() );
            if ( nRevision > 0 )
                i_xDocProps->setEditingCycles( nRevision );
        }

        if( xGlobSect->GetFileTimeValue( aDateTime, PROPID_EDITTIME ) )
        {
            // subtract offset 1601-01-01
            aDateTime.Year  -= 1601;
            aDateTime.Month -= 1;
            aDateTime.Day   -= 1;
            try
            {
                i_xDocProps->setEditingDuration(
                    aDateTime.Day     * 60*60*24 +
                    aDateTime.Hours   * 60*60    +
                    aDateTime.Minutes * 60       +
                    aDateTime.Seconds            );
            }
            catch (lang::IllegalArgumentException &)
            {
                // ignore
            }
        }
    }

    // *** custom properties from stream "005DocumentSummaryInformation" ***

    // load the property set
    SfxOlePropertySet aDocSet;
    ErrCode nDocError = aDocSet.LoadPropertySet(i_pStorage,
        String( RTL_CONSTASCII_USTRINGPARAM( STREAM_DOCSUMMARYINFO ) ) );

    // custom properties
    SfxOleSectionRef xCustomSect = aDocSet.GetSection( SECTION_CUSTOM );
    if( xCustomSect.get() )
    {
        uno::Reference < beans::XPropertyContainer > xUserDefined(
            i_xDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW);
        ::std::vector< sal_Int32 > aPropIds;
        xCustomSect->GetPropertyIds( aPropIds );
        for( ::std::vector< sal_Int32 >::const_iterator aIt = aPropIds.begin(),
             aEnd = aPropIds.end(); aIt != aEnd; ++aIt )
        {
            ::rtl::OUString aPropName = xCustomSect->GetPropertyName( *aIt );
            uno::Any aPropValue = xCustomSect->GetAnyValue( *aIt );
            if( (aPropName.getLength() > 0) && aPropValue.hasValue() ) {
                try {
                    xUserDefined->addProperty( aPropName,
                        beans::PropertyAttribute::REMOVEABLE, aPropValue );
                } catch ( uno::Exception& ) {
                    //ignore
                }
            }
        }
    }

    // return code
    return (nGlobError != ERRCODE_NONE) ? nGlobError : nDocError;
}

bool SFX2_DLLPUBLIC SaveOlePropertySet(
    uno::Reference< document::XDocumentProperties> i_xDocProps,
    SotStorage* i_pStorage,
    const uno::Sequence<sal_uInt8> * i_pThumb,
    const uno::Sequence<sal_uInt8> * i_pGuid,
    const uno::Sequence<sal_uInt8> * i_pHyperlinks)
{
    // *** global properties into stream "005SummaryInformation" ***

    SfxOlePropertySet aGlobSet;

    // set supported properties
    SfxOleSection& rGlobSect = aGlobSet.AddSection( SECTION_GLOBAL );
    rGlobSect.SetStringValue( PROPID_TITLE,    i_xDocProps->getTitle() );
    rGlobSect.SetStringValue( PROPID_SUBJECT,  i_xDocProps->getSubject() );
    String aStr = ::comphelper::string::convertCommaSeparated(
        i_xDocProps->getKeywords() );
    rGlobSect.SetStringValue( PROPID_KEYWORDS, aStr );
    rGlobSect.SetStringValue( PROPID_TEMPLATE, i_xDocProps->getTemplateName() );
    rGlobSect.SetStringValue( PROPID_COMMENTS, i_xDocProps->getDescription() );
    rGlobSect.SetStringValue( PROPID_AUTHOR,   i_xDocProps->getAuthor() );
    rGlobSect.SetFileTimeValue(PROPID_CREATED, i_xDocProps->getCreationDate());
    rGlobSect.SetStringValue( PROPID_LASTAUTHOR, i_xDocProps->getModifiedBy() );
    rGlobSect.SetFileTimeValue(PROPID_LASTSAVED,
                                i_xDocProps->getModificationDate() );
    // note: apparently PrintedBy is not supported in file format
    rGlobSect.SetFileTimeValue(PROPID_LASTPRINTED, i_xDocProps->getPrintDate());

    sal_Int32 dur = i_xDocProps->getEditingDuration();
    util::DateTime aEditTime;
    // add offset 1601-01-01
    aEditTime.Year    = 1601;
    aEditTime.Month   = 1;
    aEditTime.Day     = 1;
    aEditTime.Hours   = static_cast<sal_Int16>(dur / 3600);
    aEditTime.Minutes = static_cast<sal_Int16>((dur % 3600) / 60);
    aEditTime.Seconds = static_cast<sal_Int16>(dur % 60);
    rGlobSect.SetFileTimeValue( PROPID_EDITTIME, aEditTime );

    rGlobSect.SetStringValue( PROPID_REVNUMBER,
                String::CreateFromInt32( i_xDocProps->getEditingCycles() ) );
    if ( i_pThumb && i_pThumb->getLength() )
		rGlobSect.SetThumbnailValue( PROPID_THUMBNAIL, *i_pThumb );

    // save the property set
    ErrCode nGlobError = aGlobSet.SavePropertySet(i_pStorage,
        String( RTL_CONSTASCII_USTRINGPARAM( STREAM_SUMMARYINFO ) ) );

    // *** custom properties into stream "005DocumentSummaryInformation" ***

    SfxOlePropertySet aDocSet;

    // set builtin properties
    aDocSet.AddSection( SECTION_BUILTIN );

    // set custom properties
    SfxOleSection& rCustomSect = aDocSet.AddSection( SECTION_CUSTOM );

    // write GUID
    if (i_pGuid) {
        const sal_Int32 nPropId = rCustomSect.GetFreePropertyId();
        rCustomSect.SetBlobValue( nPropId, *i_pGuid );
        rCustomSect.SetPropertyName( nPropId,
            ::rtl::OUString::createFromAscii("_PID_GUID") );
    }

    // write hyperlinks
    if (i_pHyperlinks) {
        const sal_Int32 nPropId = rCustomSect.GetFreePropertyId();
        rCustomSect.SetBlobValue( nPropId, *i_pHyperlinks );
        rCustomSect.SetPropertyName( nPropId,
            ::rtl::OUString::createFromAscii("_PID_HLINKS") );
    }

    uno::Reference<beans::XPropertySet> xUserDefinedProps(
        i_xDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW);
    DBG_ASSERT(xUserDefinedProps.is(), "UserDefinedProperties is null");
    uno::Reference<beans::XPropertySetInfo> xPropInfo =
        xUserDefinedProps->getPropertySetInfo();
    DBG_ASSERT(xPropInfo.is(), "UserDefinedProperties Info is null");
    uno::Sequence<beans::Property> props = xPropInfo->getProperties();
    for (sal_Int32 i = 0; i < props.getLength(); ++i) {
        try {
            // skip transient properties
            if (~props[i].Attributes & beans::PropertyAttribute::TRANSIENT)
            {
                const ::rtl::OUString name = props[i].Name;
                const sal_Int32 nPropId = rCustomSect.GetFreePropertyId();
                if (rCustomSect.SetAnyValue( nPropId,
                            xUserDefinedProps->getPropertyValue(name))) {
                    rCustomSect.SetPropertyName( nPropId, name );
                }
            }
        } catch (uno::Exception &) {
            // may happen with concurrent modification...
            DBG_WARNING("SavePropertySet: exception");
        }
    }

    // save the property set
    ErrCode nDocError = aDocSet.SavePropertySet(i_pStorage,
        String( RTL_CONSTASCII_USTRINGPARAM( STREAM_DOCSUMMARYINFO ) ) );

    // return code
    return (nGlobError == ERRCODE_NONE) && (nDocError == ERRCODE_NONE);
}

uno::Sequence<sal_uInt8> SFX2_DLLPUBLIC convertMetaFile(GDIMetaFile* i_pThumb)
{
    if (i_pThumb) {
        BitmapEx aBitmap;
        SvMemoryStream aStream;
// magic value 160 taken from GraphicHelper::getThumbnailFormatFromGDI_Impl()
        if( i_pThumb->CreateThumbnail( 160, aBitmap ) ) {
            WriteDIB(aBitmap.GetBitmap(), aStream, false, false);
//            uno::Sequence<sal_uInt8> aSeq(aStream.GetSize()); // WRONG
            aStream.Seek(STREAM_SEEK_TO_END);
            uno::Sequence<sal_uInt8> aSeq(aStream.Tell());
            const sal_uInt8* pBlob(
                static_cast<const sal_uInt8*>(aStream.GetData()));
            for (sal_Int32 j = 0; j < aSeq.getLength(); ++j) {
                aSeq[j] = pBlob[j];
            }
            return aSeq;
        }
    }
    return uno::Sequence<sal_uInt8>();
}

} // namespace sfx2
