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

#include <canvas/debug.hxx>
#include <canvas/verbosetrace.hxx>
#include <canvas/canvastools.hxx>
#include <tools/diagnose_ex.h>

#include <comphelper/scopeguard.hxx> 

#include <basegfx/range/b2drectangle.hxx>
#include <basegfx/tools/canvastools.hxx>

#include <boost/cast.hpp>

#include "dx_spritecanvashelper.hxx"
#include "dx_canvascustomsprite.hxx"

#if defined(DX_DEBUG_IMAGES) 
# if OSL_DEBUG_LEVEL > 0
#  include <imdebug.h>
#  undef min
#  undef max
# endif
#endif

using namespace ::com::sun::star;

namespace dxcanvas
{
    namespace
    {
        void repaintBackground( const ::basegfx::B2DRange&		rUpdateArea,
                                const ::basegfx::B2IRange&		rOutputArea,
                                const DXSurfaceBitmapSharedPtr&	rBackBuffer )
        {
            // TODO(E1): Use numeric_cast to catch overflow here
            ::basegfx::B2IRange aActualArea( 0, 0,
                                             static_cast<sal_Int32>(rOutputArea.getWidth()),
                                             static_cast<sal_Int32>(rOutputArea.getHeight()) );
            aActualArea.intersect( fround( rUpdateArea ) );

			// repaint the given area of the screen with background content
			rBackBuffer->draw(aActualArea);
        }

        void spriteRedraw( const ::canvas::Sprite::Reference& rSprite )
        {
            // downcast to derived dxcanvas::Sprite interface, which
            // provides the actual redraw methods.
            ::boost::polymorphic_downcast< Sprite* >(
                rSprite.get() )->redraw();
        }

        void spriteRedrawStub( const ::canvas::Sprite::Reference& rSprite )
        {
            if( rSprite.is() )
            {
                // downcast to derived dxcanvas::Sprite interface, which
                // provides the actual redraw methods.
                ::boost::polymorphic_downcast< Sprite* >(
                    rSprite.get() )->redraw();
            }
        }

        void spriteRedrawStub2( const ::canvas::SpriteRedrawManager::AreaComponent& rComponent )
        {
            if( rComponent.second.getSprite().is() )
            {
                // downcast to derived dxcanvas::Sprite interface, which
                // provides the actual redraw methods.
                ::boost::polymorphic_downcast< Sprite* >(
                    rComponent.second.getSprite().get() )->redraw();
            }
        }
    }

    SpriteCanvasHelper::SpriteCanvasHelper() :
        mpSpriteSurface( NULL ),
        mpRedrawManager( NULL ),
        mpRenderModule(),
        mpSurfaceProxy(),
        mpBackBuffer(),
        maUpdateRect(),
        maScrapRect(),
        mbShowSpriteBounds( false )
    {
#if defined(VERBOSE) && defined(DBG_UTIL)
        // inverse default for verbose debug mode
        mbShowSpriteBounds = true;
#endif
    }

    void SpriteCanvasHelper::init( SpriteCanvas&                                    rParent,
                                   ::canvas::SpriteRedrawManager&					rManager,
                                   const IDXRenderModuleSharedPtr&					rRenderModule,
								   const ::canvas::ISurfaceProxyManagerSharedPtr&	rSurfaceProxy,
                                   const DXSurfaceBitmapSharedPtr&					rBackBuffer,
                                   const ::basegfx::B2ISize&						rOutputOffset )
    {
        // init base
        setDevice( rParent );
        setTarget( rBackBuffer, rOutputOffset );

        mpSpriteSurface = &rParent;
        mpRedrawManager = &rManager;
        mpRenderModule  = rRenderModule;
		mpSurfaceProxy  = rSurfaceProxy;
        mpBackBuffer    = rBackBuffer;
    }
    
    void SpriteCanvasHelper::disposing()
    {
		if(mpRenderModule)
			mpRenderModule->disposing();

        mpBackBuffer.reset();
        mpRenderModule.reset();
        mpRedrawManager = NULL;
        mpSpriteSurface = NULL;

        // forward to base
        CanvasHelper::disposing();        
    }

    uno::Reference< rendering::XAnimatedSprite > SpriteCanvasHelper::createSpriteFromAnimation( 
        const uno::Reference< rendering::XAnimation >& /*animation*/ )
    {
        return uno::Reference< rendering::XAnimatedSprite >();
    }

    uno::Reference< rendering::XAnimatedSprite > SpriteCanvasHelper::createSpriteFromBitmaps( 
        const uno::Sequence< uno::Reference< rendering::XBitmap > >& /*animationBitmaps*/, 
        sal_Int8                                                     /*interpolationMode*/ )
    {
        return uno::Reference< rendering::XAnimatedSprite >();
    }

    uno::Reference< rendering::XCustomSprite > SpriteCanvasHelper::createCustomSprite( const geometry::RealSize2D& spriteSize )
    {
        if( !mpRedrawManager )
            return uno::Reference< rendering::XCustomSprite >(); // we're disposed

        return uno::Reference< rendering::XCustomSprite >( 
            new CanvasCustomSprite( spriteSize, 
                                    mpSpriteSurface,
                                    mpRenderModule,
									mpSurfaceProxy,
                                    mbShowSpriteBounds ) );
    }

    uno::Reference< rendering::XSprite > SpriteCanvasHelper::createClonedSprite( const uno::Reference< rendering::XSprite >& /*original*/ )
    {
        return uno::Reference< rendering::XSprite >();
    }

    sal_Bool SpriteCanvasHelper::updateScreen( const ::basegfx::B2IRectangle& rCurrArea,
                                               sal_Bool                       bUpdateAll,
                                               bool&                          io_bSurfaceDirty )
    {
        if( !mpRedrawManager || 
            !mpRenderModule ||
            !mpBackBuffer )
        {
            return sal_False; // disposed, or otherwise dysfunctional
        }

#if defined(DX_DEBUG_IMAGES)
# if OSL_DEBUG_LEVEL > 0
        mpBackBuffer->imageDebugger();
# endif
#endif        

        // store current output area (need to tunnel that to the
        // background, scroll, opaque and general sprite repaint
        // routines)
        maScrapRect = rCurrArea;

        // clear area that needs to be blitted to screen beforehand
        maUpdateRect.reset();

		// TODO(P1): Might be worthwile to track areas of background
        // changes, too.        
        
        // TODO(P2): Might be worthwhile to use page-flipping only if
        // a certain percentage of screen area has changed - and
        // compose directly to the front buffer otherwise.
        if( !bUpdateAll && !io_bSurfaceDirty )
        {
            // background has not changed, so we're free to optimize
            // repaint to areas where a sprite has changed

            // process each independent area of overlapping sprites
            // separately.
            mpRedrawManager->forEachSpriteArea( *this );

            // flip primary surface to screen
            // ==============================

            // perform buffer flipping
            mpRenderModule->flip( maUpdateRect,
                                  rCurrArea );
        }
        else
        {
            // limit update to parent window area (ignored for fullscreen)
            // TODO(E1): Use numeric_cast to catch overflow here
            const ::basegfx::B2IRectangle aUpdateArea( 0,0,
                                                       static_cast<sal_Int32>(rCurrArea.getWidth()),
                                                       static_cast<sal_Int32>(rCurrArea.getHeight()) );

            // background has changed, or called requested full
            // update, or we're performing double buffering via page
            // flipping, so we currently have no choice but repaint
            // everything

            // repaint the whole screen with background content
            mpBackBuffer->draw(aUpdateArea);

			// redraw sprites
			mpRedrawManager->forEachSprite(::std::ptr_fun( &spriteRedraw ) );

            // flip primary surface to screen
            // ==============================

            // perform buffer flipping
            mpRenderModule->flip( aUpdateArea,
                                  rCurrArea );
        }

        // change record vector must be cleared, for the next turn of
        // rendering and sprite changing
        mpRedrawManager->clearChangeRecords();
        
        io_bSurfaceDirty = false;

        return sal_True;
    }

    void SpriteCanvasHelper::backgroundPaint( const ::basegfx::B2DRange& rUpdateRect )
    {
        ENSURE_OR_THROW( mpRenderModule &&
                          mpBackBuffer,
                          "SpriteCanvasHelper::backgroundPaint(): NULL device pointer " );

        repaintBackground( rUpdateRect,
                           maScrapRect,
                           mpBackBuffer );
    }

    void SpriteCanvasHelper::scrollUpdate( const ::basegfx::B2DRange& 						/*rMoveStart*/, 
                                           const ::basegfx::B2DRange& 						rMoveEnd,
                                           const ::canvas::SpriteRedrawManager::UpdateArea& rUpdateArea )
    {
        ENSURE_OR_THROW( mpRenderModule &&
                          mpBackBuffer,
                          "SpriteCanvasHelper::scrollUpdate(): NULL device pointer " );

        // round rectangles to integer pixel. Note: have to be
        // extremely careful here, to avoid off-by-one errors for
        // the destination area: otherwise, the next scroll update
        // would copy pixel that are not supposed to be part of
        // the sprite.
        const ::basegfx::B2IRange& rDestRect(
            ::canvas::tools::spritePixelAreaFromB2DRange( rMoveEnd ) );

        // not much sense in really implementing scrollUpdate here,
        // since outputting a sprite only partially would result in
        // expensive clipping. Furthermore, we cannot currently render
        // 3D directly to the front buffer, thus, would have to blit
        // the full sprite area, anyway. But at least optimized in the
        // sense that unnecessary background paints behind the sprites
        // are avoided.
        ::std::for_each( rUpdateArea.maComponentList.begin(),
                         rUpdateArea.maComponentList.end(),
                         ::std::ptr_fun( &spriteRedrawStub2 ) );

        // repaint uncovered areas from backbuffer - take the
        // _rounded_ rectangles from above, to have the update
        // consistent with the scroll above.
        ::std::vector< ::basegfx::B2DRange > aUncoveredAreas;
        ::basegfx::computeSetDifference( aUncoveredAreas,
                                         rUpdateArea.maTotalBounds,
                                         ::basegfx::B2DRange( rDestRect ) );
        ::std::for_each( aUncoveredAreas.begin(),
                         aUncoveredAreas.end(),
                         ::boost::bind( &repaintBackground,
                                        _1,
                                        ::boost::cref(maScrapRect),
                                        ::boost::cref(mpBackBuffer) ) );

        // TODO(E1): Use numeric_cast to catch overflow here
        ::basegfx::B2IRange aActualArea( 0, 0,
                                         static_cast<sal_Int32>(maScrapRect.getWidth()),
                                         static_cast<sal_Int32>(maScrapRect.getHeight()) );
        aActualArea.intersect( fround( rUpdateArea.maTotalBounds ) );
        
        // add given update area to the 'blit to foreground' rect
        maUpdateRect.expand( aActualArea );
    }
    
    void SpriteCanvasHelper::opaqueUpdate( const ::basegfx::B2DRange&                          rTotalArea,
                                           const ::std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites )
    {
        ENSURE_OR_THROW( mpRenderModule &&
                          mpBackBuffer,
                          "SpriteCanvasHelper::opaqueUpdate(): NULL device pointer " );

        // TODO(P2): optimize this by truly rendering to the front
        // buffer. Currently, we've the 3D device only for the back
        // buffer.
        ::std::for_each( rSortedUpdateSprites.begin(),
                         rSortedUpdateSprites.end(),
                         ::std::ptr_fun( &spriteRedrawStub ) );

        // TODO(E1): Use numeric_cast to catch overflow here
        ::basegfx::B2IRange aActualArea( 0, 0,
                                         static_cast<sal_Int32>(maScrapRect.getWidth()),
                                         static_cast<sal_Int32>(maScrapRect.getHeight()) );
        aActualArea.intersect( fround( rTotalArea ) );        
        
        // add given update area to the 'blit to foreground' rect
        maUpdateRect.expand( aActualArea );
    }
    
    void SpriteCanvasHelper::genericUpdate( const ::basegfx::B2DRange&                          rTotalArea,
                                            const ::std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites )
    {
		ENSURE_OR_THROW( mpRenderModule &&
                          mpBackBuffer,
                          "SpriteCanvasHelper::genericUpdate(): NULL device pointer " );

        // paint background
        // ================

        // TODO(E1): Use numeric_cast to catch overflow here
        ::basegfx::B2IRange aActualArea( 0, 0,
                                         static_cast<sal_Int32>(maScrapRect.getWidth()),
                                         static_cast<sal_Int32>(maScrapRect.getHeight()) );
        aActualArea.intersect( fround( rTotalArea ) );

		// repaint the given area of the screen with background content
		mpBackBuffer->draw(aActualArea);

        // paint sprite
        // ============

        ::std::for_each( rSortedUpdateSprites.begin(),
                         rSortedUpdateSprites.end(),
                         ::std::ptr_fun( &spriteRedrawStub ) );
        
        // add given update area to the 'blit to foreground' rect
        maUpdateRect.expand( aActualArea );
    }
}
