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

#include "PresenterPaneContainer.hxx"
#include "PresenterPaneBase.hxx"
#include <com/sun/star/awt/XGraphics.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/container/XChild.hpp>
#include <com/sun/star/drawing/framework/ResourceId.hpp>
#include <vector>

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::drawing::framework;
using ::rtl::OUString;

namespace sdext { namespace presenter {

PresenterPaneContainer::PresenterPaneContainer (
    const Reference<XComponentContext>& rxContext)
    : PresenterPaneContainerInterfaceBase(m_aMutex),
      maPanes(),
      mxPresenterHelper()
{
    Reference<lang::XMultiComponentFactory> xFactory (rxContext->getServiceManager());
    if (xFactory.is())
    {
        mxPresenterHelper = Reference<drawing::XPresenterHelper>(
            xFactory->createInstanceWithContext(
                OUString::createFromAscii("com.sun.star.comp.Draw.PresenterHelper"),
                rxContext),
            UNO_QUERY_THROW);
    }
}




PresenterPaneContainer::~PresenterPaneContainer (void)
{
}




void PresenterPaneContainer::PreparePane (
    const Reference<XResourceId>& rxPaneId,
    const OUString& rsViewURL,
    const OUString& rsTitle,
    const OUString& rsAccessibleTitle,
    const bool bIsOpaque,
    const ViewInitializationFunction& rViewInitialization,
    const double nLeft,
    const double nTop,
    const double nRight,
    const double nBottom)
{
    if ( ! rxPaneId.is())
        return;

    SharedPaneDescriptor pPane (FindPaneURL(rxPaneId->getResourceURL()));
    if (pPane.get() == NULL)
    {
        // No entry found for the given pane id.  Create a new one.
        SharedPaneDescriptor pDescriptor (new PaneDescriptor());
        pDescriptor->mxPaneId = rxPaneId;
        pDescriptor->msViewURL = rsViewURL;
        pDescriptor->mxPane = NULL;
        if (rsTitle.indexOf('%') < 0)
        {
            pDescriptor->msTitle = rsTitle;
            pDescriptor->msTitleTemplate = OUString();
        }
        else
        {
            pDescriptor->msTitleTemplate = rsTitle;
            pDescriptor->msTitle = OUString();
        }
        pDescriptor->msAccessibleTitleTemplate = rsAccessibleTitle;
        pDescriptor->maViewInitialization = rViewInitialization;
        pDescriptor->mnLeft = nLeft;
        pDescriptor->mnTop = nTop;
        pDescriptor->mnRight = nRight;
        pDescriptor->mnBottom = nBottom;
        pDescriptor->mbIsActive = true;
        pDescriptor->mbIsOpaque = bIsOpaque;
        pDescriptor->maSpriteProvider = PaneDescriptor::SpriteProvider();
        pDescriptor->mbIsSprite = false;
        pDescriptor->maCalloutAnchorLocation = awt::Point(-1,-1);
        pDescriptor->mbHasCalloutAnchor = false;

        maPanes.push_back(pDescriptor);
    }
}




void SAL_CALL PresenterPaneContainer::disposing (void)
{
    PaneList::iterator iPane (maPanes.begin());
    PaneList::const_iterator iEnd (maPanes.end());
    for ( ; iPane!=iEnd; ++iPane)
        if ((*iPane)->mxPaneId.is())
            RemovePane((*iPane)->mxPaneId);
}




PresenterPaneContainer::SharedPaneDescriptor
    PresenterPaneContainer::StorePane (const rtl::Reference<PresenterPaneBase>& rxPane)
{
    SharedPaneDescriptor pDescriptor;

    if (rxPane.is())
    {
        OUString sPaneURL;
        Reference<XResourceId> xPaneId (rxPane->getResourceId());
        if (xPaneId.is())
            sPaneURL = xPaneId->getResourceURL();

        pDescriptor = FindPaneURL(sPaneURL);
        if (pDescriptor.get() == NULL)
            PreparePane(xPaneId, OUString(), OUString(), OUString(),
                false, ViewInitializationFunction(), 0,0,0,0);
        pDescriptor = FindPaneURL(sPaneURL);
        if (pDescriptor.get() != NULL)
        {
            Reference<awt::XWindow> xWindow (rxPane->getWindow());
            pDescriptor->mxContentWindow = xWindow;
            pDescriptor->mxPaneId = xPaneId;
            pDescriptor->mxPane = rxPane;
            pDescriptor->mxPane->SetTitle(pDescriptor->msTitle);

            // When there is a call out anchor location set then tell the
            // window about it.
            if (pDescriptor->mbHasCalloutAnchor)
                pDescriptor->mxPane->SetCalloutAnchor(pDescriptor->maCalloutAnchorLocation);

            if (xWindow.is())
                xWindow->addEventListener(this);
        }
    }

    return pDescriptor;
}




PresenterPaneContainer::SharedPaneDescriptor
    PresenterPaneContainer::StoreBorderWindow(
        const Reference<XResourceId>& rxPaneId,
        const Reference<awt::XWindow>& rxBorderWindow)
{
    // The content window may not be present.  Use the resource URL of the
    // pane id as key.
    OUString sPaneURL;
    if (rxPaneId.is())
        sPaneURL = rxPaneId->getResourceURL();

    SharedPaneDescriptor pDescriptor (FindPaneURL(sPaneURL));
    if (pDescriptor.get() != NULL)
    {
        pDescriptor->mxBorderWindow = rxBorderWindow;
        return pDescriptor;
    }
    else
        return SharedPaneDescriptor();
}




PresenterPaneContainer::SharedPaneDescriptor
    PresenterPaneContainer::StoreView (
        const Reference<XView>& rxView,
        const SharedBitmapDescriptor& rpViewBackground)
{
    SharedPaneDescriptor pDescriptor;

    if (rxView.is())
    {
        OUString sPaneURL;
        Reference<XResourceId> xViewId (rxView->getResourceId());
        if (xViewId.is())
        {
            Reference<XResourceId> xPaneId (xViewId->getAnchor());
            if (xPaneId.is())
                sPaneURL = xPaneId->getResourceURL();
        }

        pDescriptor = FindPaneURL(sPaneURL);
        if (pDescriptor.get() != NULL)
        {
            pDescriptor->mxView = rxView;
            pDescriptor->mpViewBackground = rpViewBackground;
            pDescriptor->mxPane->SetBackground(rpViewBackground);
            try
            {
                if ( ! pDescriptor->maViewInitialization.empty())
                    pDescriptor->maViewInitialization(rxView);

                // Activate or deactivate the pane/view.
                if ( ! pDescriptor->maActivator.empty())
                    pDescriptor->maActivator(pDescriptor->mbIsActive);
            }
            catch (RuntimeException&)
            {
                OSL_ASSERT(false);
            }
        }
    }

    return pDescriptor;
}




PresenterPaneContainer::SharedPaneDescriptor
    PresenterPaneContainer::RemovePane (const Reference<XResourceId>& rxPaneId)
{
    SharedPaneDescriptor pDescriptor (FindPaneId(rxPaneId));
    if (pDescriptor.get() != NULL)
    {
        if (pDescriptor->mxContentWindow.is())
            pDescriptor->mxContentWindow->removeEventListener(this);
        pDescriptor->mxContentWindow = NULL;
        pDescriptor->mxBorderWindow = NULL;
        pDescriptor->mxPane = NULL;
        pDescriptor->mxView = NULL;
        pDescriptor->mbIsActive = false;
    }
    return pDescriptor;
}





PresenterPaneContainer::SharedPaneDescriptor
    PresenterPaneContainer::RemoveView (const Reference<XView>& rxView)
{
    SharedPaneDescriptor pDescriptor;

    if (rxView.is())
    {
        OUString sPaneURL;
        Reference<XResourceId> xViewId (rxView->getResourceId());
        if (xViewId.is())
        {
            Reference<XResourceId> xPaneId (xViewId->getAnchor());
            if (xPaneId.is())
                sPaneURL = xPaneId->getResourceURL();
        }

        pDescriptor = FindPaneURL(sPaneURL);
        if (pDescriptor.get() != NULL)
        {
            pDescriptor->mxView = NULL;
            pDescriptor->mpViewBackground = SharedBitmapDescriptor();
        }
    }

    return pDescriptor;
}




PresenterPaneContainer::SharedPaneDescriptor PresenterPaneContainer::FindBorderWindow (
    const Reference<awt::XWindow>& rxBorderWindow)
{
    PaneList::const_iterator iPane;
    PaneList::iterator iEnd (maPanes.end());
    for (iPane=maPanes.begin(); iPane!=iEnd; ++iPane)
    {
        if ((*iPane)->mxBorderWindow == rxBorderWindow)
            return *iPane;
    }
    return SharedPaneDescriptor();
}




PresenterPaneContainer::SharedPaneDescriptor PresenterPaneContainer::FindContentWindow (
    const Reference<awt::XWindow>& rxContentWindow)
{
    PaneList::const_iterator iPane;
    PaneList::iterator iEnd (maPanes.end());
    for (iPane=maPanes.begin(); iPane!=iEnd; ++iPane)
    {
        if ((*iPane)->mxContentWindow == rxContentWindow)
            return *iPane;
    }
    return SharedPaneDescriptor();
}




PresenterPaneContainer::SharedPaneDescriptor PresenterPaneContainer::FindPaneURL (
    const OUString& rsPaneURL)
{
    PaneList::const_iterator iPane;
    PaneList::const_iterator iEnd (maPanes.end());
    for (iPane=maPanes.begin(); iPane!=iEnd; ++iPane)
    {
        if ((*iPane)->mxPaneId->getResourceURL() == rsPaneURL)
            return *iPane;
    }
    return SharedPaneDescriptor();
}




PresenterPaneContainer::SharedPaneDescriptor PresenterPaneContainer::FindPaneId (
    const Reference<XResourceId>& rxPaneId)
{
    PaneList::iterator iEnd (maPanes.end());

    if ( ! rxPaneId.is())
        return SharedPaneDescriptor();

    PaneList::iterator iPane;
    for (iPane=maPanes.begin(); iPane!=iEnd; ++iPane)
    {
        if (rxPaneId->compareTo((*iPane)->mxPaneId) == 0)
            return *iPane;
    }
    return SharedPaneDescriptor();
}




PresenterPaneContainer::SharedPaneDescriptor PresenterPaneContainer::FindViewURL (
    const OUString& rsViewURL)
{
    PaneList::iterator iEnd (maPanes.end());
    PaneList::iterator iPane;
    for (iPane=maPanes.begin(); iPane!=iEnd; ++iPane)
    {
        if (rsViewURL == (*iPane)->msViewURL)
            return *iPane;
    }
    return SharedPaneDescriptor();
}




::rtl::OUString PresenterPaneContainer::GetPaneURLForViewURL (const ::rtl::OUString& rsViewURL)
{
    SharedPaneDescriptor pDescriptor (FindViewURL(rsViewURL));
    if (pDescriptor.get() != NULL)
        if (pDescriptor->mxPaneId.is())
            return pDescriptor->mxPaneId->getResourceURL();
    return OUString();
}




void PresenterPaneContainer::ToTop (const SharedPaneDescriptor& rpDescriptor)
{
    if (rpDescriptor.get() != NULL)
    {
        // Find iterator for pDescriptor.
        PaneList::iterator iPane;
        PaneList::iterator iEnd (maPanes.end());
        for (iPane=maPanes.begin(); iPane!=iEnd; ++iPane)
            if (iPane->get() == rpDescriptor.get())
                break;
        OSL_ASSERT(iPane!=iEnd);
        if (iPane == iEnd)
            return;

        if (mxPresenterHelper.is())
            mxPresenterHelper->toTop(rpDescriptor->mxBorderWindow);

        maPanes.erase(iPane);
        maPanes.push_back(rpDescriptor);
    }
}




//----- XEventListener --------------------------------------------------------

void SAL_CALL PresenterPaneContainer::disposing (
    const com::sun::star::lang::EventObject& rEvent)
    throw (com::sun::star::uno::RuntimeException)
{
    SharedPaneDescriptor pDescriptor (
        FindContentWindow(Reference<awt::XWindow>(rEvent.Source, UNO_QUERY)));
    if (pDescriptor.get() != NULL)
    {
        RemovePane(pDescriptor->mxPaneId);
    }
}




//===== PresenterPaneContainer::PaneDescriptor ================================

void PresenterPaneContainer::PaneDescriptor::SetActivationState (const bool bIsActive)
{
    mbIsActive = bIsActive;
    if ( ! maActivator.empty())
        maActivator(mbIsActive);
}

} } // end of namespace ::sdext::presenter
