/**************************************************************
 *
 * 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 <vcl/wrkwin.hxx>
#include <vcl/msgbox.hxx>
#include <tools/urlobj.hxx>
#include <tools/stream.hxx>
#include <sot/formats.hxx>
#include <svtools/filter.hxx>
#include <sfx2/lnkbase.hxx>
#include <sfx2/app.hxx>
#include <sfx2/progress.hxx>
#include <sfx2/docfilt.hxx>
#include <sfx2/filedlghelper.hxx>
#include <sot/exchange.hxx>
#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/uno/Sequence.hxx>
#include <sfx2/docfac.hxx>
#include <com/sun/star/document/XTypeDetection.hpp>
#include <comphelper/mediadescriptor.hxx>
#include <comphelper/processfactory.hxx>
#include <sfx2/linkmgr.hxx>
#include <sfx2/opengrf.hxx>
#include "sfx2/sfxresid.hxx"
#include "fileobj.hxx"
#include "app.hrc"
#include <vcl/dibtools.hxx>

namespace css = ::com::sun::star;

#define FILETYPE_TEXT		1
#define FILETYPE_GRF		2
#define FILETYPE_OBJECT		3

struct Impl_DownLoadData
{
	Graphic aGrf;
	Timer aTimer;

	Impl_DownLoadData( const Link& rLink )
	{
		aTimer.SetTimeout( 100 );
		aTimer.SetTimeoutHdl( rLink  );
		aGrf.SetDefaultType();
	}
	~Impl_DownLoadData()
	{
		aTimer.Stop();
	}
};

// --------------------------------------------------------------------------


SvFileObject::SvFileObject() :
	pDownLoadData( NULL ), pOldParent( NULL ), nType( FILETYPE_TEXT )
{
	bLoadAgain = sal_True;
	bSynchron = bLoadError = bWaitForData = bDataReady = bNativFormat =
	bClearMedium = bStateChangeCalled = bInCallDownLoad = sal_False;
}


SvFileObject::~SvFileObject()
{
	if ( xMed.Is() )
	{
		xMed->SetDataAvailableLink( Link() );
		xMed->SetDoneLink( Link() );
		xMed.Clear();
	}
	delete pDownLoadData;
}


sal_Bool SvFileObject::GetData( ::com::sun::star::uno::Any & rData,
								const String & rMimeType,
								sal_Bool bGetSynchron )
{
	sal_uIntPtr nFmt = SotExchange::GetFormatStringId( rMimeType );
	switch( nType )
	{
	case FILETYPE_TEXT:
		if( FORMAT_FILE == nFmt )
		{
			// das Medium muss in der Applikation geoffnet werden, um die
			// relativen Datei Links aufzuloesen!!!! Wird ueber den
			// LinkManager und damit von dessen Storage erledigt.
			rData <<= rtl::OUString( sFileNm );
		}
		break;

	case FILETYPE_GRF:
		if( !bLoadError )
		{
			SfxMediumRef xTmpMed;

			if( FORMAT_GDIMETAFILE == nFmt || FORMAT_BITMAP == nFmt ||
				SOT_FORMATSTR_ID_SVXB == nFmt )
			{
				Graphic aGrf;

				//JP 15.07.98: Bug 52959
				//		falls das Nativformat doch erwuenscht ist, muss am
				//		Ende das Flag zurueckgesetzt werden.
// wird einzig und allein im sw/ndgrf.cxx benutzt, wenn der Link vom
// GraphicNode entfernt wird.
				sal_Bool bOldNativFormat = bNativFormat;
//!!??				bNativFormat = 0 != (ASPECT_ICON & pSvData->GetAspect());

				// falls gedruckt werden soll, warten wir bis die
				// Daten vorhanden sind
				if( bGetSynchron )
				{
					// testhalber mal ein LoadFile rufen um das nach-
					// laden ueberahaupt anzustossen
					if( !xMed.Is() )
						LoadFile_Impl();

					if( !bInCallDownLoad )
					{
						xTmpMed = xMed;
						while( bWaitForData )
							Application::Reschedule();

						xMed = xTmpMed;
						bClearMedium = sal_True;
					}
				}

				if( pDownLoadData ||
					( !bWaitForData && ( xMed.Is() || 		// wurde als URL geladen
						( bSynchron && LoadFile_Impl() && xMed.Is() ) )) )
				{
					// falls

					// falls es uebers Internet gesogen wurde, nicht
					// wieder versuchen
					if( !bGetSynchron )
						bLoadAgain = !xMed->IsRemote();
					bLoadError = !GetGraphic_Impl( aGrf, xMed->GetInStream() );
				}
				else if( !LoadFile_Impl() ||
						!GetGraphic_Impl( aGrf, xMed.Is() ? xMed->GetInStream() : 0 ))
				{
					if( !xMed.Is() )
						break;
					aGrf.SetDefaultType();
				}

				if( SOT_FORMATSTR_ID_SVXB != nFmt )
					nFmt = (bLoadError || GRAPHIC_BITMAP == aGrf.GetType())
								? FORMAT_BITMAP
								: FORMAT_GDIMETAFILE;

				SvMemoryStream aMemStm( 0, 65535 );
				switch ( nFmt )
				{
				case SOT_FORMATSTR_ID_SVXB:
					if( GRAPHIC_NONE != aGrf.GetType() )
					{
						aMemStm.SetVersion( SOFFICE_FILEFORMAT_50 );
						aMemStm << aGrf;
					}
					break;

				case  FORMAT_BITMAP:
                {
                    const Bitmap aBitmap(aGrf.GetBitmap());

                    if(!aBitmap.IsEmpty())
                    {
                        WriteDIB(aBitmap, aMemStm, false, true);
                    }

                    break;
                }

				default:
					if( aGrf.GetGDIMetaFile().GetActionCount() )
					{
						GDIMetaFile aMeta( aGrf.GetGDIMetaFile() );
						aMeta.Write( aMemStm );
					}
				}
                rData <<= css::uno::Sequence< sal_Int8 >( (sal_Int8*) aMemStm.GetData(),
										aMemStm.Seek( STREAM_SEEK_TO_END ) );

				bNativFormat = bOldNativFormat;

				// alles fertig?
				if( xMed.Is() && !bSynchron && bClearMedium )
				{
					xMed.Clear();
					bClearMedium = sal_False;
				}
			}
		}
		break;
	case FILETYPE_OBJECT:
		// TODO/LATER: possibility to insert a new object
		rData <<= rtl::OUString( sFileNm );
		break;
	}
	return sal_True/*0 != aTypeList.Count()*/;
}




sal_Bool SvFileObject::Connect( sfx2::SvBaseLink* pLink )
{
	if( !pLink || !pLink->GetLinkManager() )
		return sal_False;

	// teste doch mal, ob nicht ein anderer Link mit der gleichen
	// Verbindung schon existiert
	pLink->GetLinkManager()->GetDisplayNames( pLink, 0, &sFileNm, 0, &sFilter );

	if( OBJECT_CLIENT_GRF == pLink->GetObjType() )
	{
        SfxObjectShellRef pShell = pLink->GetLinkManager()->GetPersist();
        if( pShell.Is() )
		{
			if( pShell->IsAbortingImport() )
				return sal_False;

			if( pShell->GetMedium() )
				sReferer = pShell->GetMedium()->GetName();
        }
	}

	switch( pLink->GetObjType() )
	{
	case OBJECT_CLIENT_GRF:
		nType = FILETYPE_GRF;
		bSynchron = pLink->IsSynchron();
		break;

	case OBJECT_CLIENT_FILE:
		nType = FILETYPE_TEXT;
		break;

	case OBJECT_CLIENT_OLE:
		nType = FILETYPE_OBJECT;
		// TODO/LATER: introduce own type to be used for exchanging
		break;

	default:
		return sal_False;
	}

	SetUpdateTimeout( 0 );

	// und jetzt bei diesem oder gefundenem Pseudo-Object anmelden
	AddDataAdvise( pLink, SotExchange::GetFormatMimeType( pLink->GetContentType()), 0 );
	return sal_True;
}


sal_Bool SvFileObject::LoadFile_Impl()
{
	// wir sind noch im Laden!!
	if( bWaitForData || !bLoadAgain || xMed.Is() || pDownLoadData )
		return sal_False;

	// z.Z. nur auf die aktuelle DocShell
	xMed = new SfxMedium( sFileNm, STREAM_STD_READ, sal_True );
    SvLinkSource::StreamToLoadFrom aStreamToLoadFrom =
        getStreamToLoadFrom();
    xMed->setStreamToLoadFrom(
        aStreamToLoadFrom.m_xInputStreamToLoadFrom,
        aStreamToLoadFrom.m_bIsReadOnly);
	// setStreamToLoadFrom(0,0);
	if( sReferer.Len() )
		xMed->SetReferer( sReferer );

	if( !bSynchron )
	{
		bLoadAgain = bDataReady = bInNewData = sal_False;
		bWaitForData = sal_True;

		SfxMediumRef xTmpMed = xMed;
		xMed->SetDataAvailableLink( STATIC_LINK( this, SvFileObject, LoadGrfNewData_Impl ) );
		bInCallDownLoad = sal_True;
		xMed->DownLoad( STATIC_LINK( this, SvFileObject, LoadGrfReady_Impl ) );
		bInCallDownLoad = sal_False;

		bClearMedium = !xMed.Is();
		if( bClearMedium )
			xMed = xTmpMed;		// falls gleich im DownLoad schon schluss ist
		return bDataReady;
	}

	bWaitForData = sal_True;
	bDataReady = bInNewData = sal_False;
	xMed->DownLoad();
	bLoadAgain = !xMed->IsRemote();
	bWaitForData = sal_False;

	// Grafik ist fertig, also DataChanged von der Statusaederung schicken:
	SendStateChg_Impl( xMed->GetInStream() && xMed->GetInStream()->GetError()
						? sfx2::LinkManager::STATE_LOAD_ERROR : sfx2::LinkManager::STATE_LOAD_OK );
	return sal_True;
}


sal_Bool SvFileObject::GetGraphic_Impl( Graphic& rGrf, SvStream* pStream )
{
	GraphicFilter* pGF = GraphicFilter::GetGraphicFilter();

	const sal_uInt16 nFilter = sFilter.Len() && pGF->GetImportFormatCount()
							? pGF->GetImportFormatNumber( sFilter )
							: GRFILTER_FORMAT_DONTKNOW;

	String aEmptyStr;
	int nRes;

	// vermeiden, dass ein native Link angelegt wird
	if( ( !pStream || !pDownLoadData ) && !rGrf.IsLink() &&
		!rGrf.GetContext() && !bNativFormat )
		rGrf.SetLink( GfxLink() );

	if( !pStream )
		nRes = xMed.Is() ? GRFILTER_OPENERROR
						 : pGF->ImportGraphic( rGrf, INetURLObject(sFileNm),
							nFilter );
	else if( !pDownLoadData )
	{
		pStream->Seek( STREAM_SEEK_TO_BEGIN );

        // #123042# for e.g. SVG the path is needed, see same TaskID in svx for more info
        nRes = pGF->ImportGraphic( rGrf, sFileNm, *pStream, nFilter );
	}
	else
	{
		nRes = pGF->ImportGraphic( pDownLoadData->aGrf, aEmptyStr,
									*pStream, nFilter );

		if( pDownLoadData )
		{
			rGrf = pDownLoadData->aGrf;
			if( GRAPHIC_NONE == rGrf.GetType() )
				rGrf.SetDefaultType();


			if( !pDownLoadData->aGrf.GetContext() )
			{
				xMed->SetDataAvailableLink( Link() );
//				xMed->SetDoneLink( Link() );
				delete pDownLoadData, pDownLoadData = 0;
				bDataReady = sal_True;
				bWaitForData = sal_False;
			}
			else if( sal_False )
			{
				// Timer aufsetzen, um zurueck zukehren
				pDownLoadData->aTimer.Start();
			}
		}
	}

	if( pStream && ERRCODE_IO_PENDING == pStream->GetError() )
		pStream->ResetError();

#ifdef DBG_UTIL
	if( nRes )
	{
		if( xMed.Is() && !pStream )
		{
			DBG_WARNING3( "GrafikFehler [%d] - [%s] URL[%s]",
							nRes,
							xMed->GetPhysicalName().GetBuffer(),
							sFileNm.GetBuffer() );
		}
		else
		{
			DBG_WARNING2( "GrafikFehler [%d] - [%s]",
							nRes, sFileNm.GetBuffer() );
		}
	}
#endif

	return GRFILTER_OK == nRes;
}

/** detect the filter of the given file

    @param _rURL
        specifies the URL of the file which filter is to detected.<br/>
        If the URL doesn't denote a valid (existent and accessible) file, the
        request is silently dropped.
*/
String impl_getFilter( const String& _rURL )
{
    String sFilter;
    if ( _rURL.Len() == 0 )
        return sFilter;

    try
    {
        css::uno::Reference< ::com::sun::star::document::XTypeDetection > xTypeDetection(
            ::comphelper::getProcessServiceFactory()->createInstance(
                ::rtl::OUString::createFromAscii("com.sun.star.document.TypeDetection") ),
                css::uno::UNO_QUERY );
        if ( xTypeDetection.is() )
        {
            ::comphelper::MediaDescriptor aDescr;
            aDescr[ ::comphelper::MediaDescriptor::PROP_URL() ] <<= ::rtl::OUString( _rURL );
            css::uno::Sequence< css::beans::PropertyValue > aDescrList =
                aDescr.getAsConstPropertyValueList();
            ::rtl::OUString sType = xTypeDetection->queryTypeByDescriptor( aDescrList, sal_True );
            if ( sType.getLength() )
            {
                css::uno::Reference< css::container::XNameAccess > xTypeCont( xTypeDetection,
                                                                              css::uno::UNO_QUERY );
                if ( xTypeCont.is() )
                {
                    ::comphelper::SequenceAsHashMap lTypeProps( xTypeCont->getByName( sType ) );
                    sFilter = lTypeProps.getUnpackedValueOrDefault(
                        ::rtl::OUString::createFromAscii("PreferredFilter"), ::rtl::OUString() );
                }
            }
        }
    }
    catch( const css::uno::Exception& )
    {
    }

    return sFilter;
}

void SvFileObject::Edit( Window* pParent, sfx2::SvBaseLink* pLink, const Link& rEndEditHdl )
{
    aEndEditLink = rEndEditHdl;
    String sFile, sRange, sTmpFilter;
    if( pLink && pLink->GetLinkManager() )
    {
        pLink->GetLinkManager()->GetDisplayNames( pLink, 0, &sFile, &sRange, &sTmpFilter );

        switch( pLink->GetObjType() )
        {
            case OBJECT_CLIENT_GRF:
            {
                nType = FILETYPE_GRF;       // falls noch nicht gesetzt

                SvxOpenGraphicDialog aDlg(SfxResId(RID_SVXSTR_EDITGRFLINK));
                aDlg.EnableLink(sal_False);
                aDlg.SetPath( sFile, sal_True );
                aDlg.SetCurrentFilter( sTmpFilter );

                if( !aDlg.Execute() )
                {
                    sFile = aDlg.GetPath();
                    sFile += ::sfx2::cTokenSeperator;
                    sFile += ::sfx2::cTokenSeperator;
                    sFile += aDlg.GetCurrentFilter();

                    if ( aEndEditLink.IsSet() )
                        aEndEditLink.Call( &sFile );
                }
                else
                    sFile.Erase();
            }
            break;

            case OBJECT_CLIENT_OLE:
            {
                nType = FILETYPE_OBJECT; // if not set already
                pOldParent = Application::GetDefDialogParent();
                Application::SetDefDialogParent( pParent );

                ::sfx2::FileDialogHelper* pFileDlg =
                    pLink->GetFileDialog( (SFXWB_INSERT | WB_3DLOOK), String() );
                pFileDlg->StartExecuteModal( LINK( this, SvFileObject, DialogClosedHdl ) );
            }
            break;

            case OBJECT_CLIENT_FILE:
            {
                nType = FILETYPE_TEXT; // if not set already
                pOldParent = Application::GetDefDialogParent();
                Application::SetDefDialogParent( pParent );

                String sFactory;
                SfxObjectShell* pShell = pLink->GetLinkManager()->GetPersist();
                if ( pShell )
                    sFactory = pShell->GetFactory().GetFactoryName();

                ::sfx2::FileDialogHelper* pFileDlg =
                    pLink->GetFileDialog( (SFXWB_INSERT | WB_3DLOOK), sFactory );
                pFileDlg->StartExecuteModal( LINK( this, SvFileObject, DialogClosedHdl ) );
            }
            break;

            default:
                sFile.Erase();
        }
	}
}

IMPL_STATIC_LINK( SvFileObject, LoadGrfReady_Impl, void*, EMPTYARG )
{
	// wenn wir von hier kommen, kann es kein Fehler mehr sein
	pThis->bLoadError = sal_False;
	pThis->bWaitForData = sal_False;
	pThis->bInCallDownLoad = sal_False;

	if( !pThis->bInNewData && !pThis->bDataReady )
	{
			// Grafik ist fertig, also DataChanged von der Status-
			// aederung schicken:
		pThis->bDataReady = sal_True;
		pThis->SendStateChg_Impl( sfx2::LinkManager::STATE_LOAD_OK );

			// und dann nochmal die Daten senden
		pThis->NotifyDataChanged();
	}

	if( pThis->bDataReady )
	{
		pThis->bLoadAgain = sal_True;
		if( pThis->xMed.Is() )
		{
			pThis->xMed->SetDataAvailableLink( Link() );
			pThis->xMed->SetDoneLink( Link() );

			Application::PostUserEvent(
						STATIC_LINK( pThis, SvFileObject, DelMedium_Impl ),
						new SfxMediumRef( pThis->xMed ));
			pThis->xMed.Clear();
		}
		if( pThis->pDownLoadData )
			delete pThis->pDownLoadData, pThis->pDownLoadData = 0;
	}

	return 0;
}

IMPL_STATIC_LINK( SvFileObject, DelMedium_Impl, SfxMediumRef*, pDelMed )
{
	(void)pThis;
	delete pDelMed;
	return 0;
}

IMPL_STATIC_LINK( SvFileObject, LoadGrfNewData_Impl, void*, EMPTYARG )
{
	// wenn wir von hier kommen, kann es kein Fehler mehr sein
	if( pThis->bInNewData )
		return 0;

	pThis->bInNewData = sal_True;
	pThis->bLoadError = sal_False;

	if( !pThis->pDownLoadData )
	{
		pThis->pDownLoadData = new Impl_DownLoadData(
						STATIC_LINK( pThis, SvFileObject, LoadGrfNewData_Impl ) );

		// Null-Link setzen, damit keine temporaeren Grafiken
		// rausgeswapt werden; der Filter prueft, ob schon
		// ein Link gesetzt ist => falls dies zutrifft, wird
		// _kein_ neuer Link gesetzt; der Link muss hier gesetzt werden,
		// (bevor das erste Mal gefiltert wird), um zu verhindern,
		// dass der Kontext zurueckgesetzt wird (aynchrones Laden)
		if( !pThis->bNativFormat )
		{
			static GfxLink aDummyLink;
			pThis->pDownLoadData->aGrf.SetLink( aDummyLink );
		}
	}

	pThis->NotifyDataChanged();

	SvStream* pStrm = pThis->xMed.Is() ? pThis->xMed->GetInStream() : 0;
	if( pStrm && pStrm->GetError() )
	{
		if( ERRCODE_IO_PENDING == pStrm->GetError() )
			pStrm->ResetError();

		// im DataChanged ein DataReady?
		else if( pThis->bWaitForData && pThis->pDownLoadData )
		{
			pThis->bLoadError = sal_True;
		}
	}

	if( pThis->bDataReady )
	{
		// Grafik ist fertig, also DataChanged von der Status-
		// aederung schicken:
		pThis->SendStateChg_Impl( pStrm->GetError() ? sfx2::LinkManager::STATE_LOAD_ERROR : sfx2::LinkManager::STATE_LOAD_OK );
	}

	pThis->bInNewData = sal_False;
	return 0;
}

IMPL_LINK( SvFileObject, DialogClosedHdl, sfx2::FileDialogHelper*, _pFileDlg )
{
    String sFile;
    Application::SetDefDialogParent( pOldParent );

    if ( FILETYPE_TEXT == nType || FILETYPE_OBJECT == nType )
    {
        if ( _pFileDlg && _pFileDlg->GetError() == ERRCODE_NONE )
        {
            String sURL( _pFileDlg->GetPath() );
            sFile = sURL;
            sFile += ::sfx2::cTokenSeperator;
            sFile += ::sfx2::cTokenSeperator;
            sFile += impl_getFilter( sURL );
        }
    }
    else
    {
        DBG_ERRORFILE( "SvFileObject::DialogClosedHdl(): wrong file type" );
    }

    if ( aEndEditLink.IsSet() )
        aEndEditLink.Call( &sFile );
    return 0;
}

/*	[Beschreibung]

	Die Methode stellt fest, ob aus einem DDE-Object die Daten gelesen
	werden kann.
	Zurueckgegeben wird:
		ERRCODE_NONE 			wenn sie komplett gelesen wurde
		ERRCODE_SO_PENDING		wenn sie noch nicht komplett gelesen wurde
		ERRCODE_SO_FALSE		sonst
*/
sal_Bool SvFileObject::IsPending() const
{
	return FILETYPE_GRF == nType && !bLoadError &&
			( pDownLoadData || bWaitForData );
}
sal_Bool SvFileObject::IsDataComplete() const
{
	sal_Bool bRet = sal_False;
	if( FILETYPE_GRF != nType )
		bRet = sal_True;
	else if( !bLoadError && ( !bWaitForData && !pDownLoadData ))
	{
		SvFileObject* pThis = (SvFileObject*)this;
		if( bDataReady ||
			( bSynchron && pThis->LoadFile_Impl() && xMed.Is() ) )
			bRet = sal_True;
		else
		{
			INetURLObject aUrl( sFileNm );
			if( aUrl.HasError() ||
				INET_PROT_NOT_VALID == aUrl.GetProtocol() )
				bRet = sal_True;
		}
	}
	return bRet;
}



void SvFileObject::CancelTransfers()
{
	// und aus dem Cache austragen, wenn man mitten im Laden ist
	if( !bDataReady )
	{
		// nicht noch mal aufsetzen
		bLoadAgain = sal_False;
		bDataReady = bLoadError = bWaitForData = sal_True;
		SendStateChg_Impl( sfx2::LinkManager::STATE_LOAD_ABORT );
	}
}


void SvFileObject::SendStateChg_Impl( sfx2::LinkManager::LinkState nState )
{
	if( !bStateChangeCalled && HasDataLinks() )
	{
        css::uno::Any aAny;
		aAny <<= rtl::OUString::valueOf( (sal_Int32)nState );
		DataChanged( SotExchange::GetFormatName(
						sfx2::LinkManager::RegisterStatusInfoId()), aAny );
		bStateChangeCalled = sal_True;
	}
}
