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

#include <uielement/menubarmerger.hxx>
#include <framework/addonsoptions.hxx>

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

static const char SEPARATOR_STRING[]               = "private:separator";
static const sal_uInt32 SEPARATOR_STRING_LEN       = 17;

static const char MERGECOMMAND_ADDAFTER[]          = "AddAfter";
static const sal_uInt32 MERGECOMMAND_ADDAFTER_LEN  = 8;
static const char MERGECOMMAND_ADDBEFORE[]         = "AddBefore";
static const sal_uInt32 MERGECOMMAND_ADDBEFORE_LEN = 9;
static const char MERGECOMMAND_REPLACE[]           = "Replace";
static const sal_uInt32 MERGECOMMAND_REPLACE_LEN   = 7;
static const char MERGECOMMAND_REMOVE[]            = "Remove";
static const sal_uInt32 MERGECOMMAND_REMOVE_LEN    = 6;

static const char MERGEFALLBACK_ADDPATH[]           = "AddPath";
static const char MERGEFALLBACK_ADDPATH_LEN         = 7;
static const char MERGEFALLBACK_IGNORE[]            = "Ignore";
static const char MERGEFALLBACK_IGNORE_LEN          = 6;


namespace framework
{

/**
 Check whether a module identifier is part of a context
 defined by a colon separated list of module identifier.

 @param
     rContext

     Describes a context string list where all contexts
     are delimited by a colon. For more information about
     the module identifier used as context strings see the
     IDL description of com::sun::star::frame::XModuleManager

  @param
     rModuleIdentifier

     A string describing a module identifier. See IDL
     description of com::sun::star::frame::XModuleManager.

*/
bool MenuBarMerger::IsCorrectContext( const ::rtl::OUString& rContext, const ::rtl::OUString& rModuleIdentifier )
{
    return (( rContext.getLength() == 0 ) || ( rContext.indexOf( rModuleIdentifier ) >= 0 ));
}

void MenuBarMerger::RetrieveReferencePath(
    const ::rtl::OUString& rReferencePathString,
    ::std::vector< ::rtl::OUString >& rReferencePath )
{
    const sal_Char aDelimiter = '\\';

    rReferencePath.clear();
    sal_Int32 nIndex( 0 );
	do
	{
        ::rtl::OUString aToken = rReferencePathString.getToken( 0, aDelimiter, nIndex );
        if ( aToken.getLength() > 0 )
            rReferencePath.push_back( aToken );
    }
	while ( nIndex >= 0 );
}

ReferencePathInfo MenuBarMerger::FindReferencePath(
    const ::std::vector< ::rtl::OUString >& rReferencePath,
    Menu* pMenu )
{
    sal_uInt32       i( 0 );
    const sal_uInt32 nCount( rReferencePath.size() );
    Menu*            pCurrMenu( pMenu );
    RPResultInfo     eResult( RP_OK );

    sal_Int32  nLevel( - 1 );
    sal_uInt16 nPos( MENU_ITEM_NOTFOUND );
    do
    {
        ++nLevel;
        ::rtl::OUString aCmd( rReferencePath[i] );

        if ( i == nCount-1 )
        {
            // Check last reference path element. Must be a leave (menu item).
            sal_uInt16 nTmpPos = FindMenuItem( aCmd, pCurrMenu );
            if ( nTmpPos != MENU_ITEM_NOTFOUND )
                nPos = nTmpPos;
            eResult = ( nTmpPos != MENU_ITEM_NOTFOUND ) ? RP_OK : RP_MENUITEM_NOT_FOUND;
        }
        else
        {
            // Check reference path element. Must be a node (popup menu)!
            sal_uInt16 nTmpPos = FindMenuItem( aCmd, pCurrMenu );
            if ( nTmpPos != MENU_ITEM_NOTFOUND )
            {
                sal_uInt16 nItemId = pCurrMenu->GetItemId( nTmpPos );
                Menu* pTmpMenu     = pCurrMenu->GetPopupMenu( nItemId );
                if ( pTmpMenu != 0 )
                    pCurrMenu = pTmpMenu;
                else
                {
                    nPos    = nTmpPos;
                    eResult = RP_MENUITEM_INSTEAD_OF_POPUPMENU_FOUND;
                }
            }
            else
                eResult = RP_POPUPMENU_NOT_FOUND;
        }
        i++;
    }
    while (( pCurrMenu != 0 ) && ( i < nCount ) && ( eResult == RP_OK ));

    ReferencePathInfo aResult;
    aResult.pPopupMenu = pCurrMenu;
    aResult.nPos       = nPos;
    aResult.nLevel     = nLevel;
    aResult.eResult    = eResult;

    return aResult;
}

sal_uInt16 MenuBarMerger::FindMenuItem( const ::rtl::OUString& rCmd, Menu* pCurrMenu )
{
    for ( sal_uInt16 i = 0; i < pCurrMenu->GetItemCount(); i++ )
    {
        const sal_uInt16 nItemId = pCurrMenu->GetItemId( i );
        if ( nItemId > 0 )
        {
            if ( rCmd == ::rtl::OUString( pCurrMenu->GetItemCommand( nItemId )))
                return i;
        }
    }

    return MENU_ITEM_NOTFOUND;
}

bool MenuBarMerger::CreateSubMenu(
    Menu*                     pSubMenu,
    sal_uInt16&               nItemId,
    const ::rtl::OUString&    rModuleIdentifier,
    const AddonMenuContainer& rAddonSubMenu )
{
    const sal_uInt32 nSize = rAddonSubMenu.size();
    for ( sal_uInt32 i = 0; i < nSize; i++ )
    {
        const AddonMenuItem& rMenuItem = rAddonSubMenu[i];

        if ( IsCorrectContext( rMenuItem.aContext, rModuleIdentifier ))
        {
            if ( rMenuItem.aURL.equalsAsciiL( SEPARATOR_STRING, SEPARATOR_STRING_LEN ))
            {
                pSubMenu->InsertSeparator( MENU_APPEND );
            }
            else
            {
                pSubMenu->InsertItem( nItemId, rMenuItem.aTitle, 0, MENU_APPEND );
                pSubMenu->SetItemCommand( nItemId, rMenuItem.aURL );
                if ( !rMenuItem.aSubMenu.empty() )
                {
                    PopupMenu* pPopupMenu = new PopupMenu();
                    pSubMenu->SetPopupMenu( nItemId, pPopupMenu );
                    ++nItemId;

                    CreateSubMenu( pPopupMenu, nItemId, rModuleIdentifier, rMenuItem.aSubMenu );
                }
                else
                    ++nItemId;
            }
        }
    }

    return true;
}

bool MenuBarMerger::MergeMenuItems( 
    Menu*                     pMenu,
    sal_uInt16                nPos,
    sal_uInt16                nModIndex,
    sal_uInt16&               nItemId,
    const ::rtl::OUString&    rModuleIdentifier,
    const AddonMenuContainer& rAddonMenuItems )
{
    sal_uInt16       nIndex( 0 );
    const sal_uInt32 nSize = rAddonMenuItems.size();
    for ( sal_uInt32 i = 0; i < nSize; i++ )
    {
        const AddonMenuItem& rMenuItem = rAddonMenuItems[i];

        if ( IsCorrectContext( rMenuItem.aContext, rModuleIdentifier ))
        {
            if ( rMenuItem.aURL.equalsAsciiL( SEPARATOR_STRING, SEPARATOR_STRING_LEN ))
            {
                pMenu->InsertSeparator( nPos+nModIndex+nIndex );
            }
            else
            {
                pMenu->InsertItem( nItemId, rMenuItem.aTitle, 0, nPos+nModIndex+nIndex );
                pMenu->SetItemCommand( nItemId, rMenuItem.aURL );
                if ( !rMenuItem.aSubMenu.empty() )
                {
                    PopupMenu* pSubMenu = new PopupMenu();
                    pMenu->SetPopupMenu( nItemId, pSubMenu );
                    ++nItemId;
                    
                    CreateSubMenu( pSubMenu, nItemId, rModuleIdentifier, rMenuItem.aSubMenu );
                }
                else
                    ++nItemId;
            }
            ++nIndex;
        }
    }

    return true;
}

bool MenuBarMerger::ReplaceMenuItem( 
    Menu*                     pMenu, 
    sal_uInt16                nPos, 
    sal_uInt16&               rItemId, 
    const ::rtl::OUString&    rModuleIdentifier, 
    const AddonMenuContainer& rAddonMenuItems )
{
    // There is no replace available. Therfore we first have to
    // remove the old menu entry,
    pMenu->RemoveItem( nPos );

    return MergeMenuItems( pMenu, nPos, 0, rItemId, rModuleIdentifier, rAddonMenuItems );
}

bool MenuBarMerger::RemoveMenuItems(
    Menu*                     pMenu, 
    sal_uInt16                nPos, 
    const ::rtl::OUString&    rMergeCommandParameter )
{
    const sal_uInt16 nParam( sal_uInt16( rMergeCommandParameter.toInt32() ));
    sal_uInt16       nCount( 1 );
    
    nCount = std::max( nParam, nCount );
    
    sal_uInt16 i = 0;
    while (( nPos < pMenu->GetItemCount() ) && ( i < nCount ))
    {
        pMenu->RemoveItem( nPos );
        ++i;
    }

    return true;
}

bool MenuBarMerger::ProcessMergeOperation( 
    Menu*                     pMenu, 
    sal_uInt16                nPos,
    sal_uInt16&               nItemId,
    const ::rtl::OUString&    rMergeCommand,
    const ::rtl::OUString&    rMergeCommandParameter,
    const ::rtl::OUString&    rModuleIdentifier,
    const AddonMenuContainer& rAddonMenuItems )
{
    sal_uInt16 nModIndex( 0 );

    if ( rMergeCommand.equalsAsciiL( MERGECOMMAND_ADDBEFORE, MERGECOMMAND_ADDBEFORE_LEN ))
    {
        nModIndex = 0;
        return MergeMenuItems( pMenu, nPos, nModIndex, nItemId, rModuleIdentifier, rAddonMenuItems );
    }
    else if ( rMergeCommand.equalsAsciiL( MERGECOMMAND_ADDAFTER, MERGECOMMAND_ADDAFTER_LEN ))
    {
        nModIndex = 1;
        return MergeMenuItems( pMenu, nPos, nModIndex, nItemId, rModuleIdentifier, rAddonMenuItems );
    }
    else if ( rMergeCommand.equalsAsciiL( MERGECOMMAND_REPLACE, MERGECOMMAND_REPLACE_LEN ))
    {
        return ReplaceMenuItem( pMenu, nPos, nItemId, rModuleIdentifier, rAddonMenuItems );
    }
    else if ( rMergeCommand.equalsAsciiL( MERGECOMMAND_REMOVE, MERGECOMMAND_REMOVE_LEN ))
    {
        return RemoveMenuItems( pMenu, nPos, rMergeCommandParameter );
    }

    return false;
}

bool MenuBarMerger::ProcessFallbackOperation(
    const ReferencePathInfo&                aRefPathInfo,
    sal_uInt16&                             rItemId,
    const ::rtl::OUString&                  rMergeCommand,
    const ::rtl::OUString&                  rMergeFallback,
    const ::std::vector< ::rtl::OUString >& rReferencePath,
    const ::rtl::OUString&                  rModuleIdentifier,
    const AddonMenuContainer&               rAddonMenuItems )
{
    if (( rMergeFallback.equalsAsciiL( MERGEFALLBACK_IGNORE, MERGEFALLBACK_IGNORE_LEN )) ||
        ( rMergeCommand.equalsAsciiL(  MERGECOMMAND_REPLACE, MERGECOMMAND_REPLACE_LEN )) ||
        ( rMergeCommand.equalsAsciiL(  MERGECOMMAND_REMOVE, MERGECOMMAND_REMOVE_LEN   )) )
    {
        return true;
    }
    else if ( rMergeFallback.equalsAsciiL( MERGEFALLBACK_ADDPATH, MERGEFALLBACK_ADDPATH_LEN ))
    {
        Menu*            pCurrMenu( aRefPathInfo.pPopupMenu );
        sal_Int32        nLevel( aRefPathInfo.nLevel );
        const sal_Int32  nSize( rReferencePath.size() );
        bool             bFirstLevel( true );
        
        while ( nLevel < nSize )
        {
            if ( nLevel == nSize-1 )
            {
                const sal_uInt32 nCount = rAddonMenuItems.size();
                for ( sal_uInt32 i = 0; i < nCount; ++i )
                {
                    const AddonMenuItem& rMenuItem = rAddonMenuItems[i];
                    if ( IsCorrectContext( rMenuItem.aContext, rModuleIdentifier ))
                    {
                        if ( rMenuItem.aURL.equalsAsciiL( SEPARATOR_STRING, SEPARATOR_STRING_LEN ))
                            pCurrMenu->InsertSeparator( MENU_APPEND );
                        else
                        {
                            pCurrMenu->InsertItem( rItemId, rMenuItem.aTitle, 0, MENU_APPEND );
                            pCurrMenu->SetItemCommand( rItemId, rMenuItem.aURL );
                            ++rItemId;
                        }
                    }
                }
            }
            else
            {
                const ::rtl::OUString aCmd( rReferencePath[nLevel] );
                
                sal_uInt16 nInsPos( MENU_APPEND );
                PopupMenu* pPopupMenu( new PopupMenu );
                
                if ( bFirstLevel && ( aRefPathInfo.eResult == RP_MENUITEM_INSTEAD_OF_POPUPMENU_FOUND ))
                {
                    // special case: menu item without popup
                    nInsPos = aRefPathInfo.nPos;
                    sal_uInt16 nSetItemId = pCurrMenu->GetItemId( nInsPos );
                    pCurrMenu->SetItemCommand( nSetItemId, aCmd );
                    pCurrMenu->SetPopupMenu( nSetItemId, pPopupMenu );
                }
                else                
                {
                    // normal case: insert a new item with popup
                    pCurrMenu->InsertItem( rItemId, ::rtl::OUString(), 0, MENU_APPEND );
                    pCurrMenu->SetItemCommand( rItemId, aCmd );
                    pCurrMenu->SetPopupMenu( rItemId, pPopupMenu );
                }
                
                pCurrMenu = pPopupMenu;
                ++rItemId;
                bFirstLevel = false;
            }
            ++nLevel;
        }
        return true;
    }

    return false;
}

void MenuBarMerger::GetMenuEntry( 
    const uno::Sequence< beans::PropertyValue >& rAddonMenuEntry,
    AddonMenuItem&                               rAddonMenuItem )
{
	// Reset submenu member
    rAddonMenuItem.aSubMenu.clear();
	
	for ( sal_Int32 i = 0; i < rAddonMenuEntry.getLength(); i++ )
	{
        ::rtl::OUString aMenuEntryPropName = rAddonMenuEntry[i].Name;
		if ( aMenuEntryPropName.equalsAsciiL( ADDONSMENUITEM_STRING_URL, ADDONSMENUITEM_URL_LEN ))
			rAddonMenuEntry[i].Value >>= rAddonMenuItem.aURL;
		else if ( aMenuEntryPropName.equalsAsciiL( ADDONSMENUITEM_STRING_TITLE, ADDONSMENUITEM_TITLE_LEN ))
			rAddonMenuEntry[i].Value >>= rAddonMenuItem.aTitle;
		else if ( aMenuEntryPropName.equalsAsciiL( ADDONSMENUITEM_STRING_TARGET, ADDONSMENUITEM_TARGET_LEN ))
			rAddonMenuEntry[i].Value >>= rAddonMenuItem.aTarget;
		else if ( aMenuEntryPropName.equalsAsciiL( ADDONSMENUITEM_STRING_SUBMENU, ADDONSMENUITEM_SUBMENU_LEN ))
        {
            uno::Sequence< uno::Sequence< beans::PropertyValue > > aSubMenu;
            rAddonMenuEntry[i].Value >>= aSubMenu;
            GetSubMenu( aSubMenu, rAddonMenuItem.aSubMenu );
        }
		else if ( aMenuEntryPropName.equalsAsciiL( ADDONSMENUITEM_STRING_CONTEXT, ADDONSMENUITEM_CONTEXT_LEN ))
			rAddonMenuEntry[i].Value >>= rAddonMenuItem.aContext;
		else if ( aMenuEntryPropName.equalsAsciiL( ADDONSMENUITEM_STRING_IMAGEIDENTIFIER, ADDONSMENUITEM_IMAGEIDENTIFIER_LEN ))
			rAddonMenuEntry[i].Value >>= rAddonMenuItem.aImageId;
	}
}

void MenuBarMerger::GetSubMenu(
    const uno::Sequence< uno::Sequence< beans::PropertyValue > >& rSubMenuEntries,
    AddonMenuContainer&                                           rSubMenu )
{
    rSubMenu.clear();
    
    const sal_Int32 nCount = rSubMenuEntries.getLength();
    rSubMenu.reserve(rSubMenu.size() + nCount);
    for ( sal_Int32 i = 0; i < nCount; i++ )
    {
        const uno::Sequence< beans::PropertyValue >& rMenuEntry = rSubMenuEntries[ i ];

        AddonMenuItem aMenuItem;        
        GetMenuEntry( rMenuEntry, aMenuItem );
        rSubMenu.push_back( aMenuItem );
    }
}

} // namespace framework
