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

#include "ConfigurationUpdater.hxx"
#include "ConfigurationTracer.hxx"
#include "ConfigurationClassifier.hxx"
#include "ConfigurationControllerBroadcaster.hxx"
#include "framework/Configuration.hxx"
#include "framework/FrameworkHelper.hxx"

#include <comphelper/scopeguard.hxx>
#include <tools/diagnose_ex.h>

#include <boost/bind.hpp>

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::drawing::framework;
using ::sd::framework::FrameworkHelper;
using ::rtl::OUString;
using ::std::vector;

#undef VERBOSE
//#define VERBOSE 2

namespace {
static const sal_Int32 snShortTimeout (100);
static const sal_Int32 snNormalTimeout (1000);
static const sal_Int32 snLongTimeout (10000);
static const sal_Int32 snShortTimeoutCountThreshold (1);
static const sal_Int32 snNormalTimeoutCountThreshold (5);
}

namespace sd { namespace framework {


//===== ConfigurationUpdaterLock ==============================================

class ConfigurationUpdaterLock
{
public:
    ConfigurationUpdaterLock (ConfigurationUpdater& rUpdater)
        : mrUpdater(rUpdater) { mrUpdater.LockUpdates(); }
    ~ConfigurationUpdaterLock(void) { mrUpdater.UnlockUpdates(); }
private:
    ConfigurationUpdater& mrUpdater;
};




//===== ConfigurationUpdater ==================================================

ConfigurationUpdater::ConfigurationUpdater (
    const ::boost::shared_ptr<ConfigurationControllerBroadcaster>& rpBroadcaster,
    const ::boost::shared_ptr<ConfigurationControllerResourceManager>& rpResourceManager,
    const Reference<XControllerManager>& rxControllerManager)
    : mxControllerManager(),
      mpBroadcaster(rpBroadcaster),
      mxCurrentConfiguration(Reference<XConfiguration>(new Configuration(NULL, false))),
      mxRequestedConfiguration(),
      mbUpdatePending(false),
      mbUpdateBeingProcessed(false),
      mnLockCount(0),
      maUpdateTimer(),
      mnFailedUpdateCount(0),
      mpResourceManager(rpResourceManager)
{
    // Prepare the timer that is started when after an update the current
    // and the requested configuration differ.  With the timer we try
    // updates until the two configurations are the same.
    maUpdateTimer.SetTimeout(snNormalTimeout);
    maUpdateTimer.SetTimeoutHdl(LINK(this,ConfigurationUpdater,TimeoutHandler));
    SetControllerManager(rxControllerManager);
}




ConfigurationUpdater::~ConfigurationUpdater (void)
{
    maUpdateTimer.Stop();
}




void ConfigurationUpdater::SetControllerManager(
    const Reference<XControllerManager>& rxControllerManager)
{
    mxControllerManager = rxControllerManager;
}




void ConfigurationUpdater::RequestUpdate (
    const Reference<XConfiguration>& rxRequestedConfiguration)
{
    mxRequestedConfiguration = rxRequestedConfiguration;

    // Find out whether we really can update the configuration.
    if (IsUpdatePossible())
    {
#if defined VERBOSE && VERBOSE>=1
        OSL_TRACE("UpdateConfiguration start");
#endif

        // Call UpdateConfiguration while that is possible and while someone
        // set mbUpdatePending to true in the middle of it.
        do
        {
            UpdateConfiguration();
            
            if (mbUpdatePending && IsUpdatePossible())
                continue;
        }
        while (false);
    }
    else
    {
        mbUpdatePending = true;
#if defined VERBOSE && VERBOSE>=1
        OSL_TRACE("scheduling update for later");
#endif
    }
}




Reference<XConfiguration> ConfigurationUpdater::GetCurrentConfiguration (void) const
{
    return mxCurrentConfiguration;
}




bool ConfigurationUpdater::IsUpdatePossible (void)
{
    return ! mbUpdateBeingProcessed
        && mxControllerManager.is()
        && mnLockCount==0
        && mxRequestedConfiguration.is()
        && mxCurrentConfiguration.is();
}




void ConfigurationUpdater::UpdateConfiguration (void)
{
#if defined VERBOSE && VERBOSE>=1
        OSL_TRACE("UpdateConfiguration update");
#endif
    SetUpdateBeingProcessed(true);
    comphelper::ScopeGuard aScopeGuard (
        ::boost::bind(&ConfigurationUpdater::SetUpdateBeingProcessed, this, false));

    try
    {
        mbUpdatePending = false;

        CleanRequestedConfiguration();
        ConfigurationClassifier aClassifier(mxRequestedConfiguration, mxCurrentConfiguration);
        if (aClassifier.Partition())
        {
#if defined VERBOSE && VERBOSE>=2
            OSL_TRACE("ConfigurationUpdater::UpdateConfiguration(");
            ConfigurationTracer::TraceConfiguration(
                mxRequestedConfiguration, "requested configuration");
            ConfigurationTracer::TraceConfiguration(
                mxCurrentConfiguration, "current configuration");
#endif
            // Notify the begining of the update.
            ConfigurationChangeEvent aEvent;
            aEvent.Type = FrameworkHelper::msConfigurationUpdateStartEvent;
            aEvent.Configuration = mxRequestedConfiguration;
            mpBroadcaster->NotifyListeners(aEvent);

            // Do the actual update.  All exceptions are caught and ignored,
            // so that the the end of the update is notified always.
            try
            {
                if (mnLockCount == 0)
                    UpdateCore(aClassifier);
            }
            catch(RuntimeException)
            {
            }
            
            // Notify the end of the update.
            aEvent.Type = FrameworkHelper::msConfigurationUpdateEndEvent;
            mpBroadcaster->NotifyListeners(aEvent);

            CheckUpdateSuccess();
        }
        else
        {
#if defined VERBOSE && VERBOSE>0
            OSL_TRACE("nothing to do");
#if defined VERBOSE && VERBOSE>=2
            ConfigurationTracer::TraceConfiguration(
                mxRequestedConfiguration, "requested configuration");
            ConfigurationTracer::TraceConfiguration(
                mxCurrentConfiguration, "current configuration");
#endif
#endif
        }
    }
    catch (RuntimeException e)
    {
        DBG_UNHANDLED_EXCEPTION();
    }
    
#if defined VERBOSE && VERBOSE>0
    OSL_TRACE("ConfigurationUpdater::UpdateConfiguration)");
    OSL_TRACE("UpdateConfiguration end");
#endif
}




void ConfigurationUpdater::CleanRequestedConfiguration (void)
{
    if (mxControllerManager.is())
    {
        // Request the deactivation of pure anchors that have no child.
        vector<Reference<XResourceId> > aResourcesToDeactivate;
        CheckPureAnchors(mxRequestedConfiguration, aResourcesToDeactivate);
        if (!aResourcesToDeactivate.empty() )
        {
            Reference<XConfigurationController> xCC (
                mxControllerManager->getConfigurationController());
            vector<Reference<XResourceId> >::iterator iId;
            for (iId=aResourcesToDeactivate.begin(); iId!=aResourcesToDeactivate.end(); ++iId)
                if (iId->is())
                    xCC->requestResourceDeactivation(*iId);
        }
    }
}




void ConfigurationUpdater::CheckUpdateSuccess (void)
{
    // When the two configurations differ then start the timer to call
    // another update later.
    if ( ! AreConfigurationsEquivalent(mxCurrentConfiguration, mxRequestedConfiguration))
    {
        if (mnFailedUpdateCount <= snShortTimeoutCountThreshold)
            maUpdateTimer.SetTimeout(snShortTimeout);
        else if (mnFailedUpdateCount < snNormalTimeoutCountThreshold)
            maUpdateTimer.SetTimeout(snNormalTimeout);
        else
            maUpdateTimer.SetTimeout(snLongTimeout);
        ++mnFailedUpdateCount;
        maUpdateTimer.Start();
    }
    else
    {
        // Update was successfull.  Reset the failed update count.
        mnFailedUpdateCount = 0;
    }
}




void ConfigurationUpdater::UpdateCore (const ConfigurationClassifier& rClassifier)
{
    try
    {
#if defined VERBOSE && VERBOSE>=2
        rClassifier.TraceResourceIdVector(
            "requested but not current resources:", rClassifier.GetC1minusC2());
        rClassifier.TraceResourceIdVector(
            "current but not requested resources:", rClassifier.GetC2minusC1());
        rClassifier.TraceResourceIdVector(
            "requested and current resources:", rClassifier.GetC1andC2());
#endif

        // Updating of the sub controllers is done in two steps.  In the
        // first the sub controllers typically shut down resources that are
        // not requested anymore.  In the second the sub controllers
        // typically set up resources that have been newly requested.
        mpResourceManager->DeactivateResources(rClassifier.GetC2minusC1(), mxCurrentConfiguration);
        mpResourceManager->ActivateResources(rClassifier.GetC1minusC2(), mxCurrentConfiguration);

#if defined VERBOSE && VERBOSE>=2
        OSL_TRACE("ConfigurationController::UpdateConfiguration)");
        ConfigurationTracer::TraceConfiguration(
            mxRequestedConfiguration, "requested configuration");
        ConfigurationTracer::TraceConfiguration(
            mxCurrentConfiguration, "current configuration");
#endif

        // Deactivate pure anchors that have no child.
        vector<Reference<XResourceId> > aResourcesToDeactivate;
        CheckPureAnchors(mxCurrentConfiguration, aResourcesToDeactivate);
        if (!aResourcesToDeactivate.empty() )
            mpResourceManager->DeactivateResources(aResourcesToDeactivate, mxCurrentConfiguration);
    }
    catch(RuntimeException)
    {
        DBG_UNHANDLED_EXCEPTION();
    }
}




void ConfigurationUpdater::CheckPureAnchors (
    const Reference<XConfiguration>& rxConfiguration,
    vector<Reference<XResourceId> >& rResourcesToDeactivate)
{
    if ( ! rxConfiguration.is())
        return;

    // Get a list of all resources in the configuration.
    Sequence<Reference<XResourceId> > aResources(
        rxConfiguration->getResources(
            NULL, OUString(), AnchorBindingMode_INDIRECT));
    sal_Int32 nCount (aResources.getLength());

    // Prepare the list of pure anchors that have to be deactivated.
    rResourcesToDeactivate.clear();

    // Iterate over the list in reverse order because when there is a chain
    // of pure anchors with only the last one having no child then the whole
    // list has to be deactivated.
    sal_Int32 nIndex (nCount-1);
    while (nIndex >= 0)
    {
        const Reference<XResourceId> xResourceId (aResources[nIndex]);
        const Reference<XResource> xResource (
            mpResourceManager->GetResource(xResourceId).mxResource);
        bool bDeactiveCurrentResource (false);

        // Skip all resources that are no pure anchors.
        if (xResource.is() && xResource->isAnchorOnly())
        {
            // When xResource is not an anchor of the the next resource in
            // the list then it is the anchor of no resource at all.
            if (nIndex == nCount-1)
            {
                // No following anchors, deactivate this one, then remove it
                // from the list.
                bDeactiveCurrentResource = true;
            }
            else
            {
                const Reference<XResourceId> xPrevResourceId (aResources[nIndex+1]);
                if ( ! xPrevResourceId.is()
                    || ! xPrevResourceId->isBoundTo(xResourceId, AnchorBindingMode_DIRECT))
                {
                    // The previous resource (id) does not exist or is not bound to
                    // the current anchor.
                    bDeactiveCurrentResource = true;
                }
            }
        }

        if (bDeactiveCurrentResource)
        {
#if defined VERBOSE && VERBOSE>=2
            OSL_TRACE("deactiving pure anchor %s because it has no children",
                OUStringToOString(
                    FrameworkHelper::ResourceIdToString(xResourceId),
                    RTL_TEXTENCODING_UTF8).getStr());
#endif            
            // Erase element from current configuration.
            for (sal_Int32 nI=nIndex; nI<nCount-2; ++nI)
                aResources[nI] = aResources[nI+1];
            nCount -= 1;

            rResourcesToDeactivate.push_back(xResourceId);
        }
        nIndex -= 1;
    }
}




void ConfigurationUpdater::LockUpdates (void)
{
    ++mnLockCount;
}




void ConfigurationUpdater::UnlockUpdates (void)
{
    --mnLockCount;
    if (mnLockCount == 0 && mbUpdatePending)
    {
        RequestUpdate(mxRequestedConfiguration);
    }
}




::boost::shared_ptr<ConfigurationUpdaterLock> ConfigurationUpdater::GetLock (void)
{
    return ::boost::shared_ptr<ConfigurationUpdaterLock>(new ConfigurationUpdaterLock(*this));
}




void ConfigurationUpdater::SetUpdateBeingProcessed (bool bValue)
{
    mbUpdateBeingProcessed = bValue;
}




IMPL_LINK(ConfigurationUpdater, TimeoutHandler, Timer*, EMPTYARG)
{
    OSL_TRACE("configuration update timer");
    if ( ! mbUpdateBeingProcessed
        && mxCurrentConfiguration.is()
        && mxRequestedConfiguration.is())
    {
        if ( ! AreConfigurationsEquivalent(mxCurrentConfiguration, mxRequestedConfiguration))
        {
            OSL_TRACE("configurations differ, requesting update");
            RequestUpdate(mxRequestedConfiguration);
        }
    }
    return 0;
}


} } // end of namespace sd::framework
