/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/


#include <wrtsh.hxx>
#include <shellres.hxx>
#include <swwait.hxx>
#include <view.hxx>
#include <toxmgr.hxx>
#include <crsskip.hxx>
#include <doc.hxx>
#include <IDocumentUndoRedo.hxx>
#include <swundo.hxx>
#include <globals.hrc>

/*--------------------------------------------------------------------
    Description: handle indexes with TOXMgr
 --------------------------------------------------------------------*/


SwTOXMgr::SwTOXMgr(SwWrtShell* pShell):
    pSh(pShell)
{
    GetTOXMarks();
    SetCurTOXMark(0);
}

/*--------------------------------------------------------------------
    Description: handle current TOXMarks
 --------------------------------------------------------------------*/


sal_uInt16 SwTOXMgr::GetTOXMarks()
{
    return pSh->GetCurTOXMarks(aCurMarks);
}


SwTOXMark* SwTOXMgr::GetTOXMark(sal_uInt16 nId)
{
    if(aCurMarks.Count() > 0)
        return aCurMarks[nId];
    return 0;
}


void SwTOXMgr::DeleteTOXMark()
{
    SwTOXMark* pNext = 0;
    if( pCurTOXMark )
    {
        pNext = (SwTOXMark*)&pSh->GotoTOXMark( *pCurTOXMark, TOX_NXT );
        if( pNext == pCurTOXMark )
            pNext = 0;

        pSh->DeleteTOXMark( pCurTOXMark );
        pSh->SetModified();
    }
    // go to next one
    pCurTOXMark = pNext;
}

void    SwTOXMgr::InsertTOXMark(const SwTOXMarkDescription& rDesc)
{
    SwTOXMark* pMark = 0;
    switch(rDesc.GetTOXType())
    {
        case  TOX_CONTENT:
        {
            OSL_ENSURE(rDesc.GetLevel() > 0 && rDesc.GetLevel() <= MAXLEVEL,
                       "invalid InsertTOCMark level");
            pMark = new SwTOXMark(pSh->GetTOXType(TOX_CONTENT, 0));
            pMark->SetLevel( static_cast< sal_uInt16 >(rDesc.GetLevel()) );

            if(rDesc.GetAltStr())
                pMark->SetAlternativeText(*rDesc.GetAltStr());
        }
        break;
        case  TOX_INDEX:
        {
            pMark = new SwTOXMark(pSh->GetTOXType(TOX_INDEX, 0));

            if( rDesc.GetPrimKey() && rDesc.GetPrimKey()->Len() )
            {
                pMark->SetPrimaryKey( *rDesc.GetPrimKey() );
                if(rDesc.GetPhoneticReadingOfPrimKey())
                    pMark->SetPrimaryKeyReading( *rDesc.GetPhoneticReadingOfPrimKey() );

                if( rDesc.GetSecKey() && rDesc.GetSecKey()->Len() )
                {
                    pMark->SetSecondaryKey( *rDesc.GetSecKey() );
                    if(rDesc.GetPhoneticReadingOfSecKey())
                        pMark->SetSecondaryKeyReading( *rDesc.GetPhoneticReadingOfSecKey() );
                }
            }
            if(rDesc.GetAltStr())
                pMark->SetAlternativeText(*rDesc.GetAltStr());
            if(rDesc.GetPhoneticReadingOfAltStr())
                pMark->SetTextReading( *rDesc.GetPhoneticReadingOfAltStr() );
            pMark->SetMainEntry(rDesc.IsMainEntry());
        }
        break;
        case  TOX_USER:
        {
            OSL_ENSURE(rDesc.GetLevel() > 0 && rDesc.GetLevel() <= MAXLEVEL,
                       "invalid InsertTOCMark level");
            sal_uInt16 nId = rDesc.GetTOUName() ?
                GetUserTypeID(*rDesc.GetTOUName()) : 0;
            pMark = new SwTOXMark(pSh->GetTOXType(TOX_USER, nId));
            pMark->SetLevel( static_cast< sal_uInt16 >(rDesc.GetLevel()) );

            if(rDesc.GetAltStr())
                pMark->SetAlternativeText(*rDesc.GetAltStr());
        }
        break;
        default:; //prevent warning
    }
    pSh->StartAllAction();
    pSh->SwEditShell::Insert(*pMark);
    pSh->EndAllAction();
}
/*--------------------------------------------------------------------
    Description: Update of TOXMarks
 --------------------------------------------------------------------*/


void SwTOXMgr::UpdateTOXMark(const SwTOXMarkDescription& rDesc)
{
    OSL_ENSURE(pCurTOXMark, "no current TOXMark");

    pSh->StartAllAction();
    if(pCurTOXMark->GetTOXType()->GetType() == TOX_INDEX)
    {
        if(rDesc.GetPrimKey() && rDesc.GetPrimKey()->Len() )
        {
            pCurTOXMark->SetPrimaryKey( *rDesc.GetPrimKey() );
            if(rDesc.GetPhoneticReadingOfPrimKey())
                pCurTOXMark->SetPrimaryKeyReading( *rDesc.GetPhoneticReadingOfPrimKey() );
            else
                pCurTOXMark->SetPrimaryKeyReading( aEmptyStr );

            if( rDesc.GetSecKey() && rDesc.GetSecKey()->Len() )
            {
                pCurTOXMark->SetSecondaryKey( *rDesc.GetSecKey() );
                if(rDesc.GetPhoneticReadingOfSecKey())
                    pCurTOXMark->SetSecondaryKeyReading( *rDesc.GetPhoneticReadingOfSecKey() );
                else
                    pCurTOXMark->SetSecondaryKeyReading( aEmptyStr );
            }
            else
            {
                pCurTOXMark->SetSecondaryKey( aEmptyStr );
                pCurTOXMark->SetSecondaryKeyReading( aEmptyStr );
            }
        }
        else
        {
            pCurTOXMark->SetPrimaryKey( aEmptyStr );
            pCurTOXMark->SetPrimaryKeyReading( aEmptyStr );
            pCurTOXMark->SetSecondaryKey( aEmptyStr );
            pCurTOXMark->SetSecondaryKeyReading( aEmptyStr );
        }
        if(rDesc.GetPhoneticReadingOfAltStr())
            pCurTOXMark->SetTextReading( *rDesc.GetPhoneticReadingOfAltStr() );
        else
            pCurTOXMark->SetTextReading( aEmptyStr );
        pCurTOXMark->SetMainEntry(rDesc.IsMainEntry());
    }
    else
        pCurTOXMark->SetLevel( static_cast< sal_uInt16 >(rDesc.GetLevel()) );

    if(rDesc.GetAltStr())
    {
        // JP 26.08.96: Bug 30344 - either the text of a Doc or an alternative test,
        //                          not both!
        sal_Bool bReplace = pCurTOXMark->IsAlternativeText();
        if( bReplace )
            pCurTOXMark->SetAlternativeText( *rDesc.GetAltStr() );
        else
        {
            SwTOXMark aCpy( *pCurTOXMark );
            aCurMarks.Remove(0, aCurMarks.Count());
            pSh->DeleteTOXMark(pCurTOXMark);
            aCpy.SetAlternativeText( *rDesc.GetAltStr() );
            pSh->SwEditShell::Insert( aCpy );
            pCurTOXMark = 0;
        }
    }
    pSh->SetModified();
    pSh->EndAllAction();
    // Bug 36207 pCurTOXMark points nowhere here!
    if(!pCurTOXMark)
    {
        pSh->Left(CRSR_SKIP_CHARS, sal_False, 1, sal_False );
        pSh->GetCurTOXMarks(aCurMarks);
        SetCurTOXMark(0);
    }
}


/*--------------------------------------------------------------------
    Description:    determine UserTypeID
 --------------------------------------------------------------------*/


sal_uInt16 SwTOXMgr::GetUserTypeID(const String& rStr)
{
    sal_uInt16 nSize = pSh->GetTOXTypeCount(TOX_USER);
    for(sal_uInt16 i=0; i < nSize; ++i)
    {
        const SwTOXType* pTmp = pSh->GetTOXType(TOX_USER, i);
        if(pTmp && pTmp->GetTypeName() == rStr)
            return i;
    }
    SwTOXType aUserType(TOX_USER, rStr);
    pSh->InsertTOXType(aUserType);
    return nSize;
}

/*--------------------------------------------------------------------
    Description: traveling between TOXMarks
 --------------------------------------------------------------------*/


void SwTOXMgr::NextTOXMark(sal_Bool bSame)
{
    OSL_ENSURE(pCurTOXMark, "no current TOXMark");
    if( pCurTOXMark )
    {
        SwTOXSearch eDir = bSame ? TOX_SAME_NXT : TOX_NXT;
        pCurTOXMark = (SwTOXMark*)&pSh->GotoTOXMark( *pCurTOXMark, eDir );
    }
}


void SwTOXMgr::PrevTOXMark(sal_Bool bSame)
{
    OSL_ENSURE(pCurTOXMark, "no current TOXMark");
    if( pCurTOXMark )
    {
        SwTOXSearch eDir = bSame ? TOX_SAME_PRV : TOX_PRV;
        pCurTOXMark = (SwTOXMark*)&pSh->GotoTOXMark(*pCurTOXMark, eDir );
    }
}

/*--------------------------------------------------------------------
    Description: insert keyword index
 --------------------------------------------------------------------*/
const SwTOXBase* SwTOXMgr::GetCurTOX()
{
    return pSh->GetCurTOX();
}

const SwTOXType* SwTOXMgr::GetTOXType(TOXTypes eTyp, sal_uInt16 nId) const
{
    return pSh->GetTOXType(eTyp, nId);
}

void SwTOXMgr::SetCurTOXMark(sal_uInt16 nId)
{
    pCurTOXMark = (nId < aCurMarks.Count()) ? aCurMarks[nId] : 0;
}

sal_Bool SwTOXMgr::UpdateOrInsertTOX(const SwTOXDescription& rDesc,
                                    SwTOXBase** ppBase,
                                    const SfxItemSet* pSet)
{
    SwWait aWait( *pSh->GetView().GetDocShell(), sal_True );
    sal_Bool bRet = sal_True;
    const SwTOXBase* pCurTOX = ppBase && *ppBase ? *ppBase : GetCurTOX();
    SwTOXBase* pTOX = (SwTOXBase*)pCurTOX;

    SwTOXBase * pNewTOX = NULL;

    if (pTOX)
        pNewTOX = new SwTOXBase(*pTOX);

    TOXTypes eCurTOXType = rDesc.GetTOXType();
    if(pCurTOX && !ppBase && pSh->HasSelection())
        pSh->EnterStdMode();

    switch(eCurTOXType)
    {
        case TOX_INDEX :
        {
            if(!pCurTOX || (ppBase && !(*ppBase)))
            {
                const SwTOXType* pType = pSh->GetTOXType(eCurTOXType, 0);
                SwForm aForm(eCurTOXType);
                pNewTOX = new SwTOXBase(pType, aForm, nsSwTOXElement::TOX_MARK, pType->GetTypeName());
            }
            pNewTOX->SetOptions(rDesc.GetIndexOptions());
            pNewTOX->SetMainEntryCharStyle(rDesc.GetMainEntryCharStyle());
            pSh->SetTOIAutoMarkURL(rDesc.GetAutoMarkURL());
            pSh->ApplyAutoMark();
        }
        break;
        case TOX_CONTENT :
        {
            if(!pCurTOX || (ppBase && !(*ppBase)))
            {
                const SwTOXType* pType = pSh->GetTOXType(eCurTOXType, 0);
                SwForm aForm(eCurTOXType);
                pNewTOX = new SwTOXBase(pType, aForm, rDesc.GetContentOptions(), pType->GetTypeName());
            }
            pNewTOX->SetCreate(rDesc.GetContentOptions());
            pNewTOX->SetLevel(rDesc.GetLevel());
        }
        break;
        case TOX_USER :
        {
            if(!pCurTOX || (ppBase && !(*ppBase)))
            {
                sal_uInt16 nPos  = 0;
                sal_uInt16 nSize = pSh->GetTOXTypeCount(eCurTOXType);
                for(sal_uInt16 i=0; rDesc.GetTOUName() && i < nSize; ++i)
                {   const SwTOXType* pType = pSh->GetTOXType(TOX_USER, i);
                    if(pType->GetTypeName() == *rDesc.GetTOUName())
                    {   nPos = i;
                        break;
                    }
                }
                const SwTOXType* pType = pSh->GetTOXType(eCurTOXType, nPos);

                SwForm aForm(eCurTOXType);
                pNewTOX = new SwTOXBase(pType, aForm, rDesc.GetContentOptions(), pType->GetTypeName());

            }
            else
            {
                const_cast<SwTOXBase*>( pCurTOX )->SetCreate(rDesc.GetContentOptions());
            }
            pNewTOX->SetLevelFromChapter(rDesc.IsLevelFromChapter());
        }
        break;
        case TOX_OBJECTS:
        case TOX_TABLES:
        case TOX_AUTHORITIES:
        case TOX_ILLUSTRATIONS:
        {
            //Special handling for TOX_AUTHORITY
            if(TOX_AUTHORITIES == eCurTOXType)
            {
                SwAuthorityFieldType* pFType = (SwAuthorityFieldType*)
                                                pSh->GetFldType(RES_AUTHORITY, aEmptyStr);
                if (!pFType)
                {
                    SwAuthorityFieldType const type(pSh->GetDoc());
                    pFType = static_cast<SwAuthorityFieldType*>(
                                pSh->InsertFldType(type));
                }
                pFType->SetPreSuffix(rDesc.GetAuthBrackets().GetChar(0),
                    rDesc.GetAuthBrackets().GetChar(1));
                pFType->SetSequence(rDesc.IsAuthSequence());
                SwTOXSortKey rArr[3];
                rArr[0] = rDesc.GetSortKey1();
                rArr[1] = rDesc.GetSortKey2();
                rArr[2] = rDesc.GetSortKey3();
                pFType->SetSortKeys(3, rArr);
                pFType->SetSortByDocument(rDesc.IsSortByDocument());
                pFType->SetLanguage(rDesc.GetLanguage());
                pFType->SetSortAlgorithm(rDesc.GetSortAlgorithm());

                pFType->UpdateFlds();
            }
            // TODO: consider properties of the current TOXType
            if(!pCurTOX || (ppBase && !(*ppBase)))
            {
                const SwTOXType* pType = pSh->GetTOXType(eCurTOXType, 0);
                SwForm aForm(eCurTOXType);
                pNewTOX = new SwTOXBase(
                    pType, aForm,
                    TOX_AUTHORITIES == eCurTOXType ? nsSwTOXElement::TOX_MARK : 0, pType->GetTypeName());
            }
            else
            {
                if((!ppBase || !(*ppBase)) && pSh->HasSelection())
                    pSh->DelRight();
                pNewTOX = (SwTOXBase*)pCurTOX;
            }
            pNewTOX->SetFromObjectNames(rDesc.IsCreateFromObjectNames());
            pNewTOX->SetOLEOptions(rDesc.GetOLEOptions());
        }
        break;
    }


    OSL_ENSURE(pNewTOX, "no TOXBase created!" );
    if(!pNewTOX)
        return sal_False;

    pNewTOX->SetFromChapter(rDesc.IsFromChapter());
    pNewTOX->SetSequenceName(rDesc.GetSequenceName());
    pNewTOX->SetCaptionDisplay(rDesc.GetCaptionDisplay());
    pNewTOX->SetProtected(rDesc.IsReadonly());

    for(sal_uInt16 nLevel = 0; nLevel < MAXLEVEL; nLevel++)
        pNewTOX->SetStyleNames(rDesc.GetStyleNames(nLevel), nLevel);

    if(rDesc.GetTitle())
        pNewTOX->SetTitle(*rDesc.GetTitle());
    if(rDesc.GetForm())
        pNewTOX->SetTOXForm(*rDesc.GetForm());
    pNewTOX->SetLanguage(rDesc.GetLanguage());
    pNewTOX->SetSortAlgorithm(rDesc.GetSortAlgorithm());

    if(!pCurTOX || (ppBase && !(*ppBase)) )
    {
        // when ppBase is passed over, TOXBase is only created here
        // and then inserted in a global document by the dialog
        if(ppBase)
            (*ppBase) = pNewTOX;
        else
        {
            pSh->InsertTableOf(*pNewTOX, pSet);
            delete pNewTOX;
        }
    }
    else
    {
        SwDoc * pDoc = pSh->GetDoc();

        if (pDoc->GetIDocumentUndoRedo().DoesUndo())
        {
            if (pNewTOX != NULL)
            {
                pDoc->GetIDocumentUndoRedo().DelAllUndoObj();
            }

            pDoc->GetIDocumentUndoRedo().StartUndo(UNDO_TOXCHANGE, NULL);
        }

        if (pNewTOX != NULL) // => pTOX != NULL
            pDoc->ChgTOX(*pTOX, *pNewTOX);

        bRet = pSh->UpdateTableOf(*pTOX, pSet);

        if (pDoc->GetIDocumentUndoRedo().DoesUndo())
        {
            pDoc->GetIDocumentUndoRedo().EndUndo(UNDO_TOXCHANGE, NULL);

            if (pNewTOX == NULL)
            {
                pDoc->GetIDocumentUndoRedo().DelAllUndoObj();
            }
        }
    }

    return bRet;
}

void SwTOXDescription::SetSortKeys(SwTOXSortKey eKey1,
                        SwTOXSortKey eKey2,
                            SwTOXSortKey eKey3)
{
    SwTOXSortKey aArr[3];
    sal_uInt16 nPos = 0;
    if(AUTH_FIELD_END > eKey1.eField)
        aArr[nPos++] = eKey1;
    if(AUTH_FIELD_END > eKey2.eField)
        aArr[nPos++] = eKey2;
    if(AUTH_FIELD_END > eKey3.eField)
        aArr[nPos++] = eKey3;

    eSortKey1 = aArr[0];
    eSortKey2 = aArr[1];
    eSortKey3 = aArr[2];
}

void SwTOXDescription::ApplyTo(SwTOXBase& rTOXBase)
{
    for(sal_uInt16 i = 0; i < MAXLEVEL; i++)
        rTOXBase.SetStyleNames(GetStyleNames(i), i);
    rTOXBase.SetTitle(GetTitle() ? *GetTitle() : aEmptyStr);
    rTOXBase.SetCreate(GetContentOptions());

    if(GetTOXType() == TOX_INDEX)
        rTOXBase.SetOptions(GetIndexOptions());
    if(GetTOXType() != TOX_INDEX)
        rTOXBase.SetLevel(GetLevel());
    rTOXBase.SetFromObjectNames(IsCreateFromObjectNames());
    rTOXBase.SetSequenceName(GetSequenceName());
    rTOXBase.SetCaptionDisplay(GetCaptionDisplay());
    rTOXBase.SetFromChapter(IsFromChapter());
    rTOXBase.SetProtected(IsReadonly());
    rTOXBase.SetOLEOptions(GetOLEOptions());
    rTOXBase.SetLevelFromChapter(IsLevelFromChapter());
    rTOXBase.SetLanguage(eLanguage);
    rTOXBase.SetSortAlgorithm(sSortAlgorithm);

}



/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
