/**************************************************************
 * 
 * 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 "RecentlyUsedMasterPages.hxx"
#include "MasterPageObserver.hxx"
#include "MasterPagesSelector.hxx"
#include "MasterPageDescriptor.hxx"
#include "tools/ConfigurationAccess.hxx"
#include "drawdoc.hxx"
#include "sdpage.hxx"

#include <algorithm>
#include <vector>

#include <comphelper/processfactory.hxx>
#include "unomodel.hxx"
#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
#include <com/sun/star/drawing/XDrawPages.hpp>
#include <com/sun/star/frame/XComponentLoader.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/beans/PropertyState.hpp>
#include <tools/urlobj.hxx>
#include <unotools/confignode.hxx>
#include <osl/doublecheckedlocking.h>
#include <osl/getglobalmutex.hxx>

using namespace ::std;
using ::rtl::OUString;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;


namespace {

static const OUString& GetPathToImpressConfigurationRoot (void)
{
    static const OUString sPathToImpressConfigurationRoot (
        RTL_CONSTASCII_USTRINGPARAM("/org.openoffice.Office.Impress/"));
    return sPathToImpressConfigurationRoot;
}
static const OUString& GetPathToSetNode (void)
{
    static const OUString sPathToSetNode(
        RTL_CONSTASCII_USTRINGPARAM(
            "MultiPaneGUI/ToolPanel/RecentlyUsedMasterPages"));
    return sPathToSetNode;
}


class Descriptor
{
public:
    ::rtl::OUString msURL;
    ::rtl::OUString msName;
    ::sd::sidebar::MasterPageContainer::Token maToken;
    Descriptor (const ::rtl::OUString& rsURL, const ::rtl::OUString& rsName)
        : msURL(rsURL),
          msName(rsName),
          maToken(::sd::sidebar::MasterPageContainer::NIL_TOKEN)
    {}
    Descriptor (::sd::sidebar::MasterPageContainer::Token aToken,
        const ::rtl::OUString& rsURL, const ::rtl::OUString& rsName)
        : msURL(rsURL),
          msName(rsName),
          maToken(aToken)
    {}
    class TokenComparator
    { public:
        TokenComparator(::sd::sidebar::MasterPageContainer::Token aToken)
            : maToken(aToken) {}
        bool operator () (const Descriptor& rDescriptor)
        { return maToken==rDescriptor.maToken; }
    private: ::sd::sidebar::MasterPageContainer::Token maToken;
    };
};

} // end of anonymous namespace




namespace sd { namespace sidebar {

class RecentlyUsedMasterPages::MasterPageList : public ::std::vector<Descriptor>
{
public:
    MasterPageList (void) {}
};


RecentlyUsedMasterPages* RecentlyUsedMasterPages::mpInstance = NULL;


RecentlyUsedMasterPages&  RecentlyUsedMasterPages::Instance (void)
{
    if (mpInstance == NULL)
    {
        ::osl::GetGlobalMutex aMutexFunctor;
        ::osl::MutexGuard aGuard (aMutexFunctor());
        if (mpInstance == NULL)
        {
            RecentlyUsedMasterPages* pInstance = new RecentlyUsedMasterPages();
            pInstance->LateInit();
            SdGlobalResourceContainer::Instance().AddResource (
                ::std::auto_ptr<SdGlobalResource>(pInstance));
            OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
            mpInstance = pInstance;
        }
    }
    else {
        OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
    }
    
    return *mpInstance;
}




RecentlyUsedMasterPages::RecentlyUsedMasterPages (void)
    : maListeners(),
      mpMasterPages(new MasterPageList()),
      mnMaxListSize(8),
      mpContainer(new MasterPageContainer())
{
}




RecentlyUsedMasterPages::~RecentlyUsedMasterPages (void)
{
    Link aLink (LINK(this,RecentlyUsedMasterPages,MasterPageContainerChangeListener));
    mpContainer->RemoveChangeListener(aLink);
    
    MasterPageObserver::Instance().RemoveEventListener(
        LINK(this,RecentlyUsedMasterPages,MasterPageChangeListener));
}




void RecentlyUsedMasterPages::LateInit (void)
{
    Link aLink (LINK(this,RecentlyUsedMasterPages,MasterPageContainerChangeListener));
    mpContainer->AddChangeListener(aLink);
    
    LoadPersistentValues ();
    MasterPageObserver::Instance().AddEventListener(
        LINK(this,RecentlyUsedMasterPages,MasterPageChangeListener));
}




void RecentlyUsedMasterPages::LoadPersistentValues (void)
{
    try
    {
        do
        {
            tools::ConfigurationAccess aConfiguration (
                GetPathToImpressConfigurationRoot(),
                tools::ConfigurationAccess::READ_ONLY);
            Reference<container::XNameAccess> xSet (
                aConfiguration.GetConfigurationNode(GetPathToSetNode()),
                UNO_QUERY);
            if ( ! xSet.is())
                break;

            const String sURLMemberName (OUString::createFromAscii("URL"));
            const String sNameMemberName (OUString::createFromAscii("Name"));
            OUString sURL;
            OUString sName;

            // Read the names and URLs of the master pages.
            Sequence<OUString> aKeys (xSet->getElementNames());
            mpMasterPages->clear();
            mpMasterPages->reserve(aKeys.getLength());
            for (int i=0; i<aKeys.getLength(); i++)
            {
                Reference<container::XNameAccess> xSetItem (
                    xSet->getByName(aKeys[i]), UNO_QUERY);
                if (xSetItem.is())
                {
                    Any aURL (xSetItem->getByName(sURLMemberName));
                    Any aName (xSetItem->getByName(sNameMemberName));
                    aURL >>= sURL;
                    aName >>= sName;
                    SharedMasterPageDescriptor pDescriptor (new MasterPageDescriptor(
                        MasterPageContainer::TEMPLATE,
                        -1,
                        sURL,
                        String(),
                        sName,
                        false,
                        ::boost::shared_ptr<PageObjectProvider>(
                            new TemplatePageObjectProvider(sURL)),
                        ::boost::shared_ptr<PreviewProvider>(
                            new TemplatePreviewProvider(sURL))));
                    // For user supplied templates we use a different
                    // preview provider: The preview in the document shows
                    // not only shapes on the master page but also shapes on
                    // the foreground.  This is misleading and therefore
                    // these previews are discarded and created directly
                    // from the page objects.
                    if (pDescriptor->GetURLClassification() == MasterPageDescriptor::URLCLASS_USER)
                        pDescriptor->mpPreviewProvider = ::boost::shared_ptr<PreviewProvider>(
                            new PagePreviewProvider());
                    MasterPageContainer::Token aToken (mpContainer->PutMasterPage(pDescriptor));
                    mpMasterPages->push_back(Descriptor(aToken,sURL,sName));
                }
            }

            ResolveList();
        }
        while (false);
    }
    catch (Exception&)
    {
        // Ignore exception.
    }
}




void RecentlyUsedMasterPages::SavePersistentValues (void)
{
    try
    {
        do
        {
            tools::ConfigurationAccess aConfiguration (
                GetPathToImpressConfigurationRoot(),
                tools::ConfigurationAccess::READ_WRITE);
            Reference<container::XNameContainer> xSet (
                aConfiguration.GetConfigurationNode(GetPathToSetNode()),
                UNO_QUERY);
            if ( ! xSet.is())
                break;

            // Clear the set.
            Sequence<OUString> aKeys (xSet->getElementNames());
            sal_Int32 i;
            for (i=0; i<aKeys.getLength(); i++)
                xSet->removeByName (aKeys[i]);

            // Fill it with the URLs of this object.
            const String sURLMemberName (OUString::createFromAscii("URL"));
            const String sNameMemberName (OUString::createFromAscii("Name"));
            Any aValue;
            Reference<lang::XSingleServiceFactory> xChildFactory (
                xSet, UNO_QUERY);
            if ( ! xChildFactory.is())
                break;
            MasterPageList::const_iterator iDescriptor;
            sal_Int32 nIndex(0);
            for (iDescriptor=mpMasterPages->begin();
                 iDescriptor!=mpMasterPages->end();
                 ++iDescriptor,++nIndex)
            {
                // Create new child.
                OUString sKey (OUString::createFromAscii("index_"));
                sKey += OUString::valueOf(nIndex);
                Reference<container::XNameReplace> xChild(
                    xChildFactory->createInstance(), UNO_QUERY);
                if (xChild.is())
                {
                    xSet->insertByName (sKey, makeAny(xChild));

                    aValue <<= OUString(iDescriptor->msURL);
                    xChild->replaceByName (sURLMemberName, aValue);

                    aValue <<= OUString(iDescriptor->msName);
                    xChild->replaceByName (sNameMemberName, aValue);
                }
            }

            // Write the data back to disk.
            aConfiguration.CommitChanges();
        }
        while (false);
    }
    catch (Exception&)
    {
        // Ignore exception.
    }
}




void RecentlyUsedMasterPages::AddEventListener (const Link& rEventListener)
{
    if (::std::find (
        maListeners.begin(),
        maListeners.end(),
        rEventListener) == maListeners.end())
    {
        maListeners.push_back (rEventListener);
    }
}




void RecentlyUsedMasterPages::RemoveEventListener (const Link& rEventListener)
{
    maListeners.erase (
        ::std::find (
            maListeners.begin(),
            maListeners.end(),
            rEventListener));
}




int RecentlyUsedMasterPages::GetMasterPageCount (void) const
{
    return mpMasterPages->size();
}




MasterPageContainer::Token RecentlyUsedMasterPages::GetTokenForIndex (sal_uInt32 nIndex) const
{
    if(nIndex<mpMasterPages->size())
        return (*mpMasterPages)[nIndex].maToken;
    else
        return MasterPageContainer::NIL_TOKEN;
}




void RecentlyUsedMasterPages::SendEvent (void)
{
    ::std::vector<Link>::iterator aLink (maListeners.begin());
    ::std::vector<Link>::iterator aEnd (maListeners.end());
    while (aLink!=aEnd)
    {
        aLink->Call (NULL);
        ++aLink;
    }
}




IMPL_LINK(RecentlyUsedMasterPages, MasterPageChangeListener,
    MasterPageObserverEvent*, pEvent)
{
    switch (pEvent->meType)
    {
        case MasterPageObserverEvent::ET_MASTER_PAGE_ADDED:
        case MasterPageObserverEvent::ET_MASTER_PAGE_EXISTS:
            AddMasterPage(
                mpContainer->GetTokenForStyleName(pEvent->mrMasterPageName));
            break;

        case MasterPageObserverEvent::ET_MASTER_PAGE_REMOVED:
            // Do not change the list of recently master pages (the deleted
            // page was recently used) but tell the listeners.  They may want
            // to update their lists.
            SendEvent();
            break;
    }
    return 0;
}




IMPL_LINK(RecentlyUsedMasterPages, MasterPageContainerChangeListener,
    MasterPageContainerChangeEvent*, pEvent)
{
    if (pEvent != NULL)
        switch (pEvent->meEventType)
        {
            case MasterPageContainerChangeEvent::CHILD_ADDED:
            case MasterPageContainerChangeEvent::CHILD_REMOVED:
            case MasterPageContainerChangeEvent::INDEX_CHANGED:
            case MasterPageContainerChangeEvent::INDEXES_CHANGED:
                ResolveList();
                break;

            default:
                // Ignored.
                break;
        }
    return 0;
}




void RecentlyUsedMasterPages::AddMasterPage (
    MasterPageContainer::Token aToken,
    bool bMakePersistent)
{
    // For the page to be inserted the token has to be valid and the page
    // has to have a valid URL.  This excludes master pages that do not come
    // from template files.
    if (aToken != MasterPageContainer::NIL_TOKEN
        && mpContainer->GetURLForToken(aToken).Len()>0)
    {

        MasterPageList::iterator aIterator (
            ::std::find_if(mpMasterPages->begin(),mpMasterPages->end(),
                Descriptor::TokenComparator(aToken)));
        if (aIterator != mpMasterPages->end())
        {
            // When an entry for the given token already exists then remove
            // it now and insert it later at the head of the list.
            mpMasterPages->erase (aIterator);
        }

        mpMasterPages->insert(mpMasterPages->begin(),
            Descriptor(
                aToken,
                mpContainer->GetURLForToken(aToken),
                mpContainer->GetStyleNameForToken(aToken)));

        // Shorten list to maximal size.
        while (mpMasterPages->size() > mnMaxListSize)
        {
            mpMasterPages->pop_back ();
        }

        if (bMakePersistent)
            SavePersistentValues ();
        SendEvent();
    }
}




void RecentlyUsedMasterPages::ResolveList (void)
{
    bool bNotify (false);

    MasterPageList::iterator iDescriptor;
    for (iDescriptor=mpMasterPages->begin(); iDescriptor!=mpMasterPages->end(); ++iDescriptor)
    {
        if (iDescriptor->maToken == MasterPageContainer::NIL_TOKEN)
        {
            MasterPageContainer::Token aToken (mpContainer->GetTokenForURL(iDescriptor->msURL));
            iDescriptor->maToken = aToken;
            if (aToken != MasterPageContainer::NIL_TOKEN)
                bNotify = true;
        }
        else
        {
            if ( ! mpContainer->HasToken(iDescriptor->maToken))
            {
                iDescriptor->maToken = MasterPageContainer::NIL_TOKEN;
                bNotify = true;
            }
        }
    }

    if (bNotify)
        SendEvent();
}


} } // end of namespace sd::sidebar
