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

#include <comphelper/processfactory.hxx>
#include <com/sun/star/sheet/XSheetCellRange.hpp>
#include "docuno.hxx"
#include "tabvwsh.hxx"
#include "transobj.hxx"
#include "scmod.hxx"
#include "cellsuno.hxx"

namespace ooo {
namespace vba {
namespace excel {

using namespace ::com::sun::star;
using namespace ::ooo::vba;

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

ScDocShell* GetDocShellFromRange( const uno::Reference< uno::XInterface >& xRange ) throw ( uno::RuntimeException )
{
    ScCellRangesBase* pScCellRangesBase = ScCellRangesBase::getImplementation( xRange );
    if ( !pScCellRangesBase )
    {
        throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Failed to access underlying doc shell uno range object" ) ), uno::Reference< uno::XInterface >() );
    }
    return pScCellRangesBase->GetDocShell();
}

ScDocument* GetDocumentFromRange( const uno::Reference< uno::XInterface >& xRange ) throw ( uno::RuntimeException )
{
        ScDocShell* pDocShell = GetDocShellFromRange( xRange );
        if ( !pDocShell )
        {
                throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Failed to access underlying document from uno range object" ) ), uno::Reference< uno::XInterface >() );
        }
        return pDocShell->GetDocument();
}

void implSetZoom( const uno::Reference< frame::XModel >& xModel, sal_Int16 nZoom, std::vector< SCTAB >& nTabs )
{
    ScTabViewShell* pViewSh = excel::getBestViewShell( xModel );
    Fraction aFract( nZoom, 100 );
    pViewSh->GetViewData()->SetZoom( aFract, aFract, nTabs );
    pViewSh->RefreshZoom();
}
bool isInPrintPreview( SfxViewFrame* pView )
{
	sal_uInt16 nViewNo = SID_VIEWSHELL1 - SID_VIEWSHELL0;
	if ( pView->GetObjectShell()->GetFactory().GetViewFactoryCount() >
nViewNo && !pView->GetObjectShell()->IsInPlaceActive() )
	{
		SfxViewFactory &rViewFactory =
			pView->GetObjectShell()->GetFactory().GetViewFactory(nViewNo);
		if (  pView->GetCurViewId() == rViewFactory.GetOrdinal() )
			return true;
	}
	return false;
}

const ::rtl::OUString REPLACE_CELLS_WARNING(  RTL_CONSTASCII_USTRINGPARAM( "ReplaceCellsWarning"));

class PasteCellsWarningReseter
{
private:
	bool bInitialWarningState;
	static uno::Reference< beans::XPropertySet > getGlobalSheetSettings() throw ( uno::RuntimeException )
	{
		static uno::Reference< beans::XPropertySet > xTmpProps( ::comphelper::getProcessServiceFactory(), uno::UNO_QUERY_THROW );
		static uno::Reference<uno::XComponentContext > xContext( xTmpProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))), uno::UNO_QUERY_THROW );
		static uno::Reference<lang::XMultiComponentFactory > xServiceManager(
				xContext->getServiceManager(), uno::UNO_QUERY_THROW );
		static uno::Reference< beans::XPropertySet > xProps( xServiceManager->createInstanceWithContext( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sheet.GlobalSheetSettings" ) ) ,xContext ), uno::UNO_QUERY_THROW );
		return xProps;
	}

	bool getReplaceCellsWarning() throw ( uno::RuntimeException )
	{
		sal_Bool res = sal_False;
		getGlobalSheetSettings()->getPropertyValue( REPLACE_CELLS_WARNING ) >>= res;
		return ( res == sal_True );
	}

	void setReplaceCellsWarning( bool bState ) throw ( uno::RuntimeException )
	{
		getGlobalSheetSettings()->setPropertyValue( REPLACE_CELLS_WARNING, uno::makeAny( bState ) );
	}
public:
	PasteCellsWarningReseter() throw ( uno::RuntimeException )
	{
		bInitialWarningState = getReplaceCellsWarning();
		if ( bInitialWarningState )
			setReplaceCellsWarning( false );
	}
	~PasteCellsWarningReseter()
	{
		if ( bInitialWarningState )
		{
			// don't allow dtor to throw
			try
			{
				setReplaceCellsWarning( true );
			}
			catch ( uno::Exception& /*e*/ ){}
		}
	}
};

void
implnPaste( const uno::Reference< frame::XModel>& xModel )
{
	PasteCellsWarningReseter resetWarningBox;
	ScTabViewShell* pViewShell = getBestViewShell( xModel );
	if ( pViewShell )
	{
		pViewShell->PasteFromSystem();
		pViewShell->CellContentChanged();
	}
}


void
implnCopy( const uno::Reference< frame::XModel>& xModel )
{
	ScTabViewShell* pViewShell = getBestViewShell( xModel );
	if ( pViewShell )
    {
		pViewShell->CopyToClip(NULL,false,false,true);

        // mark the copied transfer object so it is used in ScVbaRange::Insert
        ScTransferObj* pClipObj = ScTransferObj::GetOwnClipboard( NULL );
        if (pClipObj)
            pClipObj->SetUseInApi( true );
    }
}

void 
implnCut( const uno::Reference< frame::XModel>& xModel )
{
	ScTabViewShell* pViewShell =  getBestViewShell( xModel );
	if ( pViewShell )
    {
		pViewShell->CutToClip( NULL, sal_True );

        // mark the copied transfer object so it is used in ScVbaRange::Insert
        ScTransferObj* pClipObj = ScTransferObj::GetOwnClipboard( NULL );
        if (pClipObj)
            pClipObj->SetUseInApi( true );
    }
}

void implnPasteSpecial( const uno::Reference< frame::XModel>& xModel, sal_uInt16 nFlags,sal_uInt16 nFunction,sal_Bool bSkipEmpty, sal_Bool bTranspose)
{
	PasteCellsWarningReseter resetWarningBox;
	sal_Bool bAsLink(sal_False), bOtherDoc(sal_False);
	InsCellCmd eMoveMode = INS_NONE;

	ScTabViewShell* pTabViewShell = getBestViewShell( xModel );
	if ( pTabViewShell )
	{
		ScViewData* pView = pTabViewShell->GetViewData();	
		Window* pWin = ( pView != NULL ) ? pView->GetActiveWin() : NULL;
		if ( pView && pWin )
		{
			if ( bAsLink && bOtherDoc )
				pTabViewShell->PasteFromSystem(0);//SOT_FORMATSTR_ID_LINK
			else 
			{
				ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pWin );
				ScDocument* pDoc = NULL; 
				if ( pOwnClip )
                {
					pDoc = pOwnClip->GetDocument();	
                    pOwnClip->SetUseInApi( false );     // don't use in Insert after it was pasted once
                }
				pTabViewShell->PasteFromClip( nFlags, pDoc,
					nFunction, bSkipEmpty, bTranspose, bAsLink,
					eMoveMode, IDF_NONE, sal_True );
				pTabViewShell->CellContentChanged();
			}
		}
	}

}

ScDocShell* 
getDocShell( const css::uno::Reference< css::frame::XModel>& xModel ) 
{
	uno::Reference< uno::XInterface > xIf( xModel, uno::UNO_QUERY_THROW );
	ScModelObj* pModel = dynamic_cast< ScModelObj* >( xIf.get() );
	ScDocShell* pDocShell = NULL;
	if ( pModel )
		pDocShell = (ScDocShell*)pModel->GetEmbeddedObject();
	return pDocShell;

}

ScTabViewShell* 
getBestViewShell( const css::uno::Reference< css::frame::XModel>& xModel )
{
	ScDocShell* pDocShell = getDocShell( xModel );
	if ( pDocShell )
		return pDocShell->GetBestViewShell();
	return NULL;
}

ScTabViewShell* 
getCurrentBestViewShell(  const uno::Reference< uno::XComponentContext >& xContext )
{ 
	uno::Reference< frame::XModel > xModel = getCurrentExcelDoc( xContext );
	return getBestViewShell( xModel );
}

SfxViewFrame* 
getViewFrame( const uno::Reference< frame::XModel >& xModel )
{
	ScTabViewShell* pViewShell = getBestViewShell( xModel );	
	if ( pViewShell )
		return pViewShell->GetViewFrame();
	return NULL;
}

uno::Reference< XHelperInterface >
getUnoSheetModuleObj( const uno::Reference< sheet::XSpreadsheet >& xSheet ) throw ( uno::RuntimeException )
{
    uno::Reference< beans::XPropertySet > xProps( xSheet, uno::UNO_QUERY_THROW );
    rtl::OUString sCodeName;
    xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("CodeName") ) ) >>= sCodeName;
    // #TODO #FIXME ideally we should 'throw' here if we don't get a valid parent, but... it is possible
    // to create a module ( and use 'Option VBASupport 1' ) for a calc document, in this scenario there
    // are *NO* special document module objects ( of course being able to switch between vba/non vba mode at
    // the document in the future could fix this, especially IF the switching of the vba mode takes care to
    // create the special document module objects if they don't exist.
    return getUnoDocModule( sCodeName, GetDocShellFromRange( xSheet ) );
}

uno::Reference< XHelperInterface >
getUnoSheetModuleObj( const uno::Reference< table::XCellRange >& xRange ) throw ( uno::RuntimeException )
{
    uno::Reference< sheet::XSheetCellRange > xSheetRange( xRange, uno::UNO_QUERY_THROW );
    uno::Reference< sheet::XSpreadsheet > xSheet( xSheetRange->getSpreadsheet(), uno::UNO_SET_THROW );
    return getUnoSheetModuleObj( xSheet );
}

uno::Reference< XHelperInterface > 
getUnoSheetModuleObj( const uno::Reference< sheet::XSheetCellRangeContainer >& xRanges ) throw ( uno::RuntimeException )
{
    uno::Reference< container::XEnumerationAccess > xEnumAccess( xRanges, uno::UNO_QUERY_THROW );
    uno::Reference< container::XEnumeration > xEnum = xEnumAccess->createEnumeration();
    uno::Reference< table::XCellRange > xRange( xEnum->nextElement(), uno::UNO_QUERY_THROW );
    return getUnoSheetModuleObj( xRange );
}

uno::Reference< XHelperInterface >
getUnoSheetModuleObj( const uno::Reference< table::XCell >& xCell ) throw ( uno::RuntimeException )
{
    uno::Reference< sheet::XSheetCellRange > xSheetRange( xCell, uno::UNO_QUERY_THROW );
    uno::Reference< sheet::XSpreadsheet > xSheet( xSheetRange->getSpreadsheet(), uno::UNO_SET_THROW );
    return getUnoSheetModuleObj( xSheet );
}

uno::Reference< XHelperInterface >
getUnoSheetModuleObj( const uno::Reference< frame::XModel >& xModel, SCTAB nTab ) throw ( uno::RuntimeException )
{
    uno::Reference< sheet::XSpreadsheetDocument > xDoc( xModel, uno::UNO_QUERY_THROW );
    uno::Reference< container::XIndexAccess > xSheets( xDoc->getSheets(), uno::UNO_QUERY_THROW );
    uno::Reference< sheet::XSpreadsheet > xSheet( xSheets->getByIndex( nTab ), uno::UNO_QUERY_THROW );
    return getUnoSheetModuleObj( xSheet );
}

SfxItemSet*
ScVbaCellRangeAccess::GetDataSet( ScCellRangesBase* pRangeObj )
{
	return pRangeObj ? pRangeObj->GetCurrentDataSet( true ) : 0;
}

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

} // namespace excel
} // namespace vba
} // namespace ooo
