/**************************************************************
 *
 * 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 "impviewframe.hxx"
#include "statcach.hxx"
#include "sfx2/viewfac.hxx"
#include "workwin.hxx"

#include "sfx2/app.hxx"
#include "sfx2/bindings.hxx"
#include "sfx2/ctrlitem.hxx"
#include "sfx2/dispatch.hxx"
#include "sfx2/docfac.hxx"
#include "sfx2/docfile.hxx"
#include "sfx2/objitem.hxx"
#include "sfx2/objsh.hxx"
#include "sfx2/request.hxx"
#include "sfx2/viewfrm.hxx"
#include "sfx2/viewsh.hxx"

#include <com/sun/star/beans/NamedValue.hpp>
#include <com/sun/star/beans/XMaterialHolder.hpp>
#include <com/sun/star/util/XCloseable.hpp>

#include <comphelper/componentcontext.hxx>
#include <comphelper/namedvaluecollection.hxx>
#include <comphelper/processfactory.hxx>
#include <svtools/asynclink.hxx>
#include <svl/eitem.hxx>
#include <svl/intitem.hxx>
#include <svl/rectitem.hxx>
#include <svl/stritem.hxx>
#include <tools/diagnose_ex.h>
#include <tools/urlobj.hxx>
#include <unotools/bootstrap.hxx>
#include <unotools/configmgr.hxx>
#include <vcl/window.hxx>

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::frame;
using namespace ::com::sun::star::util;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::beans;
using ::com::sun::star::lang::XMultiServiceFactory;
using ::com::sun::star::lang::XComponent;

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

static ::rtl::OUString GetModuleName_Impl( const ::rtl::OUString& sDocService )
{
    uno::Reference< container::XNameAccess > xMM( ::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString::createFromAscii("com.sun.star.frame.ModuleManager")), uno::UNO_QUERY );
    ::rtl::OUString sVar;
    if ( !xMM.is() )
        return sVar;

    try
    {
        ::comphelper::NamedValueCollection aAnalyzer( xMM->getByName( sDocService ) );
        sVar = aAnalyzer.getOrDefault( "ooSetupFactoryUIName", ::rtl::OUString() );
    }
    catch( uno::Exception& )
    {
        sVar = ::rtl::OUString();
    }

    return sVar;
}

//--------------------------------------------------------------------
void SfxFrameViewWindow_Impl::StateChanged( StateChangedType nStateChange )
{
	if ( nStateChange == STATE_CHANGE_INITSHOW )
    {
        SfxObjectShell* pDoc = pFrame->GetObjectShell();
        if ( pDoc && !pFrame->IsVisible() )
            pFrame->Show();

        pFrame->Resize();
    }
	else
        Window::StateChanged( nStateChange );
}

void SfxFrameViewWindow_Impl::Resize()
{
    if ( IsReallyVisible() || IsReallyShown() || GetOutputSizePixel().Width() )
        pFrame->Resize();
}

static String _getTabString()
{
    String result;

    Reference < XMaterialHolder > xHolder(
        ::comphelper::getProcessServiceFactory()->createInstance(
        DEFINE_CONST_UNICODE("com.sun.star.tab.tabreg") ), UNO_QUERY );
    if (xHolder.is())
    {
        rtl::OUString aTabString;
        Sequence< NamedValue > sMaterial;
        if (xHolder->getMaterial() >>= sMaterial) {
            for (int i=0; i < sMaterial.getLength(); i++) {
                if ((sMaterial[i].Name.equalsAscii("title")) &&
                    (sMaterial[i].Value >>= aTabString))
                {
                    result += ' ';
                    result += String(aTabString);
                }
            }
        }
    }
    return result;
}

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

//--------------------------------------------------------------------
String SfxViewFrame::UpdateTitle()

/*	[Beschreibung]

	Mit dieser Methode kann der SfxViewFrame gezwungen werden, sich sofort
	den neuen Titel vom der <SfxObjectShell> zu besorgen.

	[Anmerkung]

	Dies ist z.B. dann notwendig, wenn man der SfxObjectShell als SfxListener
	zuh"ort und dort auf den <SfxSimpleHint> SFX_HINT_TITLECHANGED reagieren
	m"ochte, um dann die Titel seiner Views abzufragen. Diese Views (SfxTopViewFrames)
	jedoch sind ebenfalls SfxListener und da die Reihenfolge der Benachrichtigung
	nicht feststeht, mu\s deren Titel-Update vorab erzwungen werden.


	[Beispiel]

	void SwDocShell::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
	{
		if ( rHint.IsA(TYPE(SfxSimpleHint)) )
		{
			switch( ( (SfxSimpleHint&) rHint ).GetId() )
			{
				case SFX_HINT_TITLECHANGED:
					for ( SfxViewFrame *pTop = SfxViewFrame::GetFirst( this );
						  pTop;
						  pTop = SfxViewFrame::GetNext( this );
					{
						pTop->UpdateTitle();
						... pTop->GetName() ...
					}
					break;
				...
			}
		}
	}
*/

{
	DBG_CHKTHIS(SfxViewFrame, 0);

    const SfxObjectFactory &rFact = GetObjectShell()->GetFactory();
    pImp->aFactoryName = String::CreateFromAscii( rFact.GetShortName() );

    SfxObjectShell *pObjSh = GetObjectShell();
	if ( !pObjSh )
        return String();

//    if  ( pObjSh->GetCreateMode() == SFX_CREATE_MODE_EMBEDDED )
//        // kein UpdateTitle mit Embedded-ObjectShell
//        return String();

    const SfxMedium *pMedium = pObjSh->GetMedium();
	String aURL;
	GetFrame();  // -Wall required??
    if ( pObjSh->HasName() )
	{
		INetURLObject aTmp( pMedium->GetName() );
        aURL = aTmp.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
	}

	if ( aURL != pImp->aActualURL )
        // URL hat sich ge"andert
		pImp->aActualURL = aURL;

    // gibt es noch eine weitere View?
    sal_uInt16 nViews=0;
    for ( SfxViewFrame *pView= GetFirst(pObjSh);
          pView && nViews<2;
          pView = GetNext(*pView,pObjSh) )
        if ( ( pView->GetFrameType() & SFXFRAME_HASTITLE ) &&
             !IsDowning_Impl())
            nViews++;

    // Titel des Fensters
    String aTitle;
    if ( nViews == 2 || pImp->nDocViewNo > 1 )
        // dann die Nummer dranh"angen
        aTitle = pObjSh->UpdateTitle( NULL, pImp->nDocViewNo );
    else
        aTitle = pObjSh->UpdateTitle();

    // Name des SbxObjects
    String aSbxName = pObjSh->SfxShell::GetName();
    if ( IsVisible() )
    {
        aSbxName += ':';
        aSbxName += String::CreateFromInt32(pImp->nDocViewNo);
    }

    SetName( aSbxName );
    pImp->aFrameTitle = aTitle;
    GetBindings().Invalidate( SID_FRAMETITLE );
    GetBindings().Invalidate( SID_CURRENT_URL );

    ::rtl::OUString aProductName;
    ::utl::ConfigManager::GetDirectConfigProperty(::utl::ConfigManager::PRODUCTNAME) >>= aProductName;

    aTitle += String::CreateFromAscii( " - " );
    aTitle += String(aProductName);
    aTitle += ' ';
    ::rtl::OUString aDocServiceName( GetObjectShell()->GetFactory().GetDocumentServiceName() );
    aTitle += String( GetModuleName_Impl( aDocServiceName ) );
#ifdef DBG_UTIL
	::rtl::OUString	aDefault;
	aTitle += DEFINE_CONST_UNICODE(" [");
	String aVerId( utl::Bootstrap::getBuildIdData( aDefault ));
	aTitle += aVerId;
	aTitle += ']';
#endif

    // append TAB string if available
    aTitle += _getTabString();

    GetBindings().Invalidate( SID_NEWDOCDIRECT );

    /* AS_TITLE
    Window* pWindow = GetFrame()->GetTopWindow_Impl();
    if ( pWindow && pWindow->GetText() != aTitle )
        pWindow->SetText( aTitle );
    */
	return aTitle;
}

void SfxViewFrame::Exec_Impl(SfxRequest &rReq )
{
	// Wenn gerade die Shells ausgetauscht werden...
	if ( !GetObjectShell() || !GetViewShell() )
		return;

	switch ( rReq.GetSlot() )
	{
        case SID_SHOWPOPUPS :
        {
			SFX_REQUEST_ARG(rReq, pShowItem, SfxBoolItem, SID_SHOWPOPUPS, sal_False);
			sal_Bool bShow = pShowItem ? pShowItem->GetValue() : sal_True;
			SFX_REQUEST_ARG(rReq, pIdItem, SfxUInt16Item, SID_CONFIGITEMID, sal_False);
			sal_uInt16 nId = pIdItem ? pIdItem->GetValue() : 0;

			// ausfuehren
            SfxWorkWindow *pWorkWin = GetFrame().GetWorkWindow_Impl();
			if ( bShow )
			{
				// Zuerst die Floats auch anzeigbar machen
				pWorkWin->MakeChildsVisible_Impl( bShow );
                GetDispatcher()->Update_Impl( sal_True );

				// Dann anzeigen
                GetBindings().HidePopups( !bShow );
			}
            else
			{
				// Alles hiden
				SfxBindings *pBind = &GetBindings();
				while ( pBind )
				{
					pBind->HidePopupCtrls_Impl( !bShow );
					pBind = pBind->GetSubBindings_Impl();
				}

				pWorkWin->HidePopups_Impl( !bShow, sal_True, nId );
				pWorkWin->MakeChildsVisible_Impl( bShow );
			}

            Invalidate( rReq.GetSlot() );
            rReq.Done();
			break;
        }

		case SID_ACTIVATE:
		{
            MakeActive_Impl( sal_True );
            rReq.SetReturnValue( SfxObjectItem( 0, this ) );
			break;
		}

        case SID_NEWDOCDIRECT :
        {
            SFX_REQUEST_ARG( rReq, pFactoryItem, SfxStringItem, SID_NEWDOCDIRECT, sal_False);
            String aFactName;
            if ( pFactoryItem )
                aFactName = pFactoryItem->GetValue();
            else if ( pImp->aFactoryName.Len() )
				aFactName = pImp->aFactoryName;
			else
            {
                DBG_ERROR("Missing argument!");
                break;
            }

            SfxRequest aReq( SID_OPENDOC, SFX_CALLMODE_SYNCHRON, GetPool() );
            String aFact = String::CreateFromAscii("private:factory/");
            aFact += aFactName;
            aReq.AppendItem( SfxStringItem( SID_FILE_NAME, aFact ) );
            aReq.AppendItem( SfxFrameItem( SID_DOCFRAME, &GetFrame() ) );
            aReq.AppendItem( SfxStringItem( SID_TARGETNAME, String::CreateFromAscii( "_blank" ) ) );
            SFX_APP()->ExecuteSlot( aReq );
            const SfxViewFrameItem* pItem = PTR_CAST( SfxViewFrameItem, aReq.GetReturnValue() );
            if ( pItem )
                rReq.SetReturnValue( SfxFrameItem( 0, pItem->GetFrame() ) );
            break;
        }

        case SID_CLOSEWIN:
		{
			// disable CloseWin, if frame is not a task
            Reference < XCloseable > xTask( GetFrame().GetFrameInterface(),  UNO_QUERY );
			if ( !xTask.is() )
				break;

			if ( GetViewShell()->PrepareClose() )
			{
                // weitere Views auf dasselbe Doc?
				SfxObjectShell *pDocSh = GetObjectShell();
				int bOther = sal_False;
				for ( const SfxViewFrame* pFrame = SfxViewFrame::GetFirst( pDocSh );
					  !bOther && pFrame;
					  pFrame = SfxViewFrame::GetNext( *pFrame, pDocSh ) )
					bOther = (pFrame != this);

                // Doc braucht nur gefragt zu werden, wenn keine weitere View
				sal_Bool bClosed = sal_False;
                sal_Bool bUI = sal_True;
                if ( ( bOther || pDocSh->PrepareClose( bUI ) ) )
				{
					if ( !bOther )
                    	pDocSh->SetModified( sal_False );
					rReq.Done(); // unbedingt vor Close() rufen!
                    bClosed = sal_False;
	                try
	                {
	                    xTask->close(sal_True);
	                    bClosed = sal_True;
	                }
	                catch( CloseVetoException& )
	                {
	                    bClosed = sal_False;
	                }
				}

				rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), bClosed ));
			}
			return;
		}
	}

	rReq.Done();
}

void SfxViewFrame::GetState_Impl( SfxItemSet &rSet )
{
	SfxObjectShell *pDocSh = GetObjectShell();

	if ( !pDocSh )
		return;

	const sal_uInt16 *pRanges = rSet.GetRanges();
	DBG_ASSERT(pRanges, "Set ohne Bereich");
	while ( *pRanges )
	{
		for ( sal_uInt16 nWhich = *pRanges++; nWhich <= *pRanges; ++nWhich )
		{
			switch(nWhich)
			{
            case SID_NEWDOCDIRECT :
            {
				if ( pImp->aFactoryName.Len() )
				{
	                String aFact = String::CreateFromAscii("private:factory/");
		            aFact += pImp->aFactoryName;
	                rSet.Put( SfxStringItem( nWhich, aFact ) );
				}
                break;
            }

			case SID_NEWWINDOW:
				rSet.DisableItem(nWhich);
				break;

			case SID_CLOSEWIN:
			{
				// disable CloseWin, if frame is not a task
                Reference < XCloseable > xTask( GetFrame().GetFrameInterface(),  UNO_QUERY );
				if ( !xTask.is() )
					rSet.DisableItem(nWhich);
				break;
			}

            case SID_SHOWPOPUPS :
				break;

            case SID_OBJECT:
                if ( GetViewShell() && GetViewShell()->GetVerbs().getLength() && !GetObjectShell()->IsInPlaceActive() )
	            {
		            uno::Any aAny;
		            aAny <<= GetViewShell()->GetVerbs();
                    rSet.Put( SfxUnoAnyItem( sal_uInt16( SID_OBJECT ), aAny ) );
	            }
                else
                    rSet.DisableItem( SID_OBJECT );
                break;

			default:
				DBG_ERROR( "invalid message-id" );
			}
		}
		++pRanges;
	}
}

void SfxViewFrame::INetExecute_Impl( SfxRequest &rRequest )
{
	sal_uInt16 nSlotId = rRequest.GetSlot();
	switch( nSlotId )
	{
		case SID_BROWSE_FORWARD:
		case SID_BROWSE_BACKWARD:
            OSL_ENSURE( false, "SfxViewFrame::INetExecute_Impl: SID_BROWSE_FORWARD/BACKWARD are dead!" );
			break;
		case SID_CREATELINK:
		{
/*! (pb) we need new implementation to create a link
*/
			break;
		}
		case SID_FOCUSURLBOX:
		{
            SfxStateCache *pCache = GetBindings().GetAnyStateCache_Impl( SID_OPENURL );
			if( pCache )
			{
				SfxControllerItem* pCtrl = pCache->GetItemLink();
				while( pCtrl )
				{
                    pCtrl->StateChanged( SID_FOCUSURLBOX, SFX_ITEM_UNKNOWN, 0 );
					pCtrl = pCtrl->GetItemLink();
				}
			}
		}
	}

	// Recording
	rRequest.Done();
}

void SfxViewFrame::INetState_Impl( SfxItemSet &rItemSet )
{
	rItemSet.DisableItem( SID_BROWSE_FORWARD );
	rItemSet.DisableItem( SID_BROWSE_BACKWARD );

    // Add/SaveToBookmark bei BASIC-IDE, QUERY-EDITOR etc. disablen
	SfxObjectShell *pDocSh = GetObjectShell();
    sal_Bool bPseudo = pDocSh && !( pDocSh->GetFactory().GetFlags() & SFXOBJECTSHELL_HASOPENDOC );
    sal_Bool bEmbedded = pDocSh && pDocSh->GetCreateMode() == SFX_CREATE_MODE_EMBEDDED;
	if ( !pDocSh || bPseudo || bEmbedded || !pDocSh->HasName() )
		rItemSet.DisableItem( SID_CREATELINK );
}

void SfxViewFrame::SetZoomFactor( const Fraction &rZoomX, const Fraction &rZoomY )
{
	GetViewShell()->SetZoomFactor( rZoomX, rZoomY );
}

void SfxViewFrame::Activate( sal_Bool bMDI )
{
	DBG_ASSERT(GetViewShell(), "Keine Shell");
    if ( bMDI )
        pImp->bActive = sal_True;
//(mba): hier evtl. wie in Beanframe NotifyEvent ?!
}

void SfxViewFrame::Deactivate( sal_Bool bMDI )
{
	DBG_ASSERT(GetViewShell(), "Keine Shell");
    if ( bMDI )
        pImp->bActive = sal_False;
//(mba): hier evtl. wie in Beanframe NotifyEvent ?!
}
