/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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 for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: IBM Corporation
 *
 *  Copyright: 2008 by IBM Corporation
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
/*************************************************************************
 * @file
 *  For LWP filter architecture prototype
 ************************************************************************/
/*************************************************************************
 * Change History
 Jan 2005			Created
 ************************************************************************/

#include "lwpfoundry.hxx"
#include "lwpfilehdr.hxx"
#include "lwpdoc.hxx"
#include "lwpmarker.hxx"
#include "lwpholder.hxx"
#include "lwpbulletstylemgr.hxx"
#include "lwpcontent.hxx"
#include "lwpvpointer.hxx"
#include "lwpsection.hxx"
#include "lwpcharacterstyle.hxx"
#include "lwpglobalmgr.hxx"

LwpFoundry::LwpFoundry(LwpObjectStream *pStrm, LwpDocument* pDoc)
    : m_pDoc(pDoc), m_pPieceMgr(NULL), m_pStyleMgr(NULL)
{
    Read(pStrm);
    m_pDropcapMgr = new LwpDropcapMgr;
    m_pBulletStyleMgr = new LwpBulletStyleMgr();
    m_pBulletStyleMgr->SetFoundry(this);
}

LwpFoundry::~LwpFoundry()
{
    if(m_pPieceMgr)
    {
        delete m_pPieceMgr;
    }
    if(m_pStyleMgr)
    {
        delete m_pStyleMgr;
    }
    if (m_pDropcapMgr)
        delete m_pDropcapMgr;
    if (m_pBulletStyleMgr)
    {
        delete m_pBulletStyleMgr;
    }
}

void LwpFoundry::Read(LwpObjectStream *pStrm)
{
    if (!m_pDoc->IsChildDoc())
    {
        m_VerMgr.Read(pStrm);
    }
    m_ObjMgr.Read(pStrm);

    m_MarkerHead.ReadIndexed(pStrm);
    m_FootnoteMgr.ReadIndexed(pStrm);

    m_NumMgr.Read(pStrm);
    m_BulMgr.Read(pStrm);

    m_SectionList.Read(pStrm);
    m_Layout.ReadIndexed(pStrm);

    ReadStyles(pStrm);

    m_BookMarkHead.ReadIndexed(pStrm);
    m_DdeLinkHead.ReadIndexed(pStrm);
    m_DirtBagHead.ReadIndexed(pStrm);
    m_NamedOutlineSeqHead.ReadIndexed(pStrm);

    m_EnumLayoutHead.ReadIndexed(pStrm);
    m_EnumLayoutTail.ReadIndexed(pStrm);
    m_NamedObjects.ReadIndexed(pStrm);

    pStrm->QuickRead(&m_nLastClickHere, sizeof(m_nLastClickHere));
    m_SmartTextMgr.ReadIndexed(pStrm);

    m_ContentMgr.Read(pStrm);
    m_FontMgr.Read(pStrm);

    if (!m_pDoc->IsChildDoc() && LwpFileHeader::m_nFileRevision >= 0x000B)
    {
        m_pPieceMgr = new LwpPieceManager();

        m_pPieceMgr->Read(pStrm);
    }

    if( LwpFileHeader::m_nFileRevision >= 0x000B)
    {
        m_DftDropCapStyle.ReadIndexed(pStrm);
    }
    if( LwpFileHeader::m_nFileRevision >= 0x000F)
    {
        m_DftHeaderStyle.ReadIndexed(pStrm);
        m_DftFooterStyle.ReadIndexed(pStrm);
    }
    pStrm->SkipExtra();

    m_pStyleMgr = new LwpStyleManager();
    m_pStyleMgr->SetFoundry(this);
}


void LwpFoundry::ReadStyles(LwpObjectStream *pStrm)
{
    m_TextStyle.ReadIndexed(pStrm);
    m_DefaultTextStyle.ReadIndexed(pStrm);
    m_DefaultClickStyle.ReadIndexed(pStrm);
    m_PageStyle.ReadIndexed(pStrm);
    m_FrameStyle.ReadIndexed(pStrm);

    m_TableStyle.ReadIndexed(pStrm);
    m_CellStyle.ReadIndexed(pStrm);
    m_DftFrameStyle.ReadIndexed(pStrm);
    m_DftPageStyle.ReadIndexed(pStrm);
    m_DftTableStyle.ReadIndexed(pStrm);

    m_DftCellStyle.ReadIndexed(pStrm);
    m_DftColumnStyle.ReadIndexed(pStrm);
    m_DftLeftColumnStyle.ReadIndexed(pStrm);
    m_DftRighColumnStyle.ReadIndexed(pStrm);

}

#include "xfilter/xfstylemanager.hxx"
#include "lwplayout.hxx"

void LwpFoundry::RegisterAllLayouts()
{
    //Register CellStyle
    LwpObject* pStyle = m_CellStyle.obj();
    if( pStyle )
    {
        pStyle->SetFoundry(this);
        pStyle->RegisterStyle();
    }

    //register content page layout list: Layout
     pStyle = m_Layout.obj();
    if( pStyle )
    {
        pStyle->SetFoundry(this);
        pStyle->RegisterStyle();
    }

    //Register page style layout list: PageStyle, such as "Default Page"
    pStyle = m_PageStyle.obj();
    if( pStyle )
    {
        pStyle->SetFoundry(this);
        pStyle->RegisterStyle();
    }

    //Register FrameStyle
    pStyle = m_FrameStyle.obj();
    if( pStyle )
    {
        pStyle->SetFoundry(this);
        pStyle->RegisterStyle();
    }

}

LwpBookMark* LwpFoundry::GetBookMark(LwpObjectID objMarker)
{
    LwpDLVListHeadHolder* pHeadHolder= static_cast
                    <LwpDLVListHeadHolder*>(m_BookMarkHead.obj());
    LwpObjectID* pObjID = pHeadHolder->GetHeadID();
    LwpBookMark* pBookMark;
    if (pObjID)
        pBookMark = static_cast<LwpBookMark*>(pObjID->obj());
    else
        return NULL;

    while (pBookMark)
    {
        if (pBookMark->IsRightMarker(objMarker))
            return pBookMark;
        pObjID = pBookMark->GetNext();
        if (pObjID)
            pBookMark = static_cast<LwpBookMark*>(pObjID->obj());
        else
            return NULL;
    }
    return NULL;
}

sal_Bool LwpFoundry::FindBookMarkByName(OUString sName)
{
    LwpDLVListHeadHolder* pHeadHolder= static_cast
                    <LwpDLVListHeadHolder*>(m_BookMarkHead.obj());
    LwpObjectID* pObjID = pHeadHolder->GetHeadID();
    LwpBookMark* pBookMark;
    if (pObjID)
        pBookMark = static_cast<LwpBookMark*>(pObjID->obj());
    else
        return sal_False;

    while (pBookMark)
    {
        if (pBookMark->IsRightName(sName))
            return sal_True;
        pObjID = pBookMark->GetNext();
        if (pObjID)
            pBookMark = static_cast<LwpBookMark*>(pObjID->obj());
        else
            return sal_False;
    }
    return sal_False;
}

/**
* @descr: 	Get next content
*
*/
LwpContent* LwpFoundry::EnumContents(LwpContent * pContent)
{
    return GetContentManager()->EnumContents(pContent);
}

/**
* @descr: 	Get next section
*
*/
LwpSection* LwpFoundry::EnumSections(LwpSection * pSection)
{
    return static_cast<LwpSection*>(m_SectionList.Enumerate(pSection));
}

/**
* @descr: 	Get default text style id
*
*/
LwpObjectID * LwpFoundry::GetDefaultTextStyle()
{
    LwpVersionedPointer * pPointer = static_cast<LwpVersionedPointer *>(m_DefaultTextStyle.obj());
    if (!pPointer)
        return NULL;

    return pPointer->GetPointer();
}

/**
* @descr: 	Get paragraph style object id according to its style name
*
*/
LwpObjectID * LwpFoundry::FindParaStyleByName(OUString name)
{
    //Register all text styles: para styles, character styles
    LwpDLVListHeadHolder* pParaStyleHolder = static_cast<LwpDLVListHeadHolder*>(GetTextStyleHead()->obj());
    if(pParaStyleHolder)
    {
        LwpTextStyle* pParaStyle = static_cast<LwpTextStyle*> (pParaStyleHolder->GetHeadID()->obj());
        while(pParaStyle)
        {
            OUString strName = pParaStyle->GetName()->str();
            if(strName == name)
                return pParaStyle->GetObjectID();
            pParaStyle = static_cast<LwpTextStyle*>(pParaStyle->GetNext()->obj());
        }
    }

    return NULL;
}

/**
* @descr: 	Get style name registed according the original style name
*
*/
OUString LwpFoundry::FindActuralStyleName(OUString name)
{
    LwpObjectID* pID = FindParaStyleByName(name);
    if(pID)
    {
        IXFStyle* pStyle = GetStyleManager()->GetStyle(*pID);
        if(pStyle)
        {
            return pStyle->GetStyleName();
        }
    }

    return name;
}

void LwpVersionManager::Read(LwpObjectStream *pStrm)
{
    // TODO: skip the data for prototype
    Skip(pStrm);
}

void LwpVersionManager::Skip(LwpObjectStream *pStrm)
{

    sal_uInt32 cNextUserVersionID;
    pStrm->QuickRead(&cNextUserVersionID, sizeof(cNextUserVersionID));

    sal_uInt16 Count;
    pStrm->QuickRead(&Count, sizeof(Count));

    sal_uInt32 tag;
    while(Count--)
    {
        pStrm->QuickRead(&tag, sizeof(tag));
        USHORT len;
        switch(tag)
        {
            case TAG_USER_VERSION:
                // TODO: skip the CUserVersionControl
                pStrm->QuickRead(&len, sizeof(len));
                pStrm->SeekRel(len);
                //pStrm->SkipExtra(); //The length has included the extra
                break;

            default:
                pStrm->QuickRead(&len, sizeof(USHORT));
                pStrm->SeekRel(len);
                pStrm->SkipExtra();
                break;
        }
    }
    pStrm->SkipExtra();
}

void LwpObjectManager::Read(LwpObjectStream *pStrm)
{

    LwpObjectID dummy;
    dummy.Read(pStrm);
    // TODO: judge if we need to set the cDelta by the dummy id

    m_Division.ReadIndexed(pStrm);
    pStrm->SkipExtra();
}

void LwpNumberManager::Read(LwpObjectStream *pStrm)
{
    m_TableRange.ReadIndexed(pStrm);
    pStrm->SkipExtra();
}

void LwpBulletManager::Read(LwpObjectStream *pStrm)
{
    m_Head.ReadIndexed(pStrm);
    pStrm->SkipExtra();
}

void LwpContentManager::Read(LwpObjectStream *pStrm)
{
    m_ContentList.ReadIndexed(pStrm);

    // TODO:  to judge the file revision

    m_EnumHead.ReadIndexed(pStrm);
    m_EnumTail.ReadIndexed(pStrm);

    m_OleObjCount.ReadIndexed(pStrm);

    if( LwpFileHeader::m_nFileRevision >= 0x000B)
    {
        m_GrapHead.ReadIndexed(pStrm);
        m_GrapTail.ReadIndexed(pStrm);
        m_OleHead.ReadIndexed(pStrm);
        m_OleTail.ReadIndexed(pStrm);
    }

    pStrm->SkipExtra();
}

/**
* @descr: 	Get next content
*
*/
LwpContent* LwpContentManager::EnumContents(LwpContent* pContent)
{
    if(pContent)
        return pContent->GetNextEnumerated();
    LwpVersionedPointer* pPointer = static_cast<LwpVersionedPointer*>(m_EnumHead.obj());
    return pPointer ? static_cast<LwpContent*>(pPointer->GetPointer()->obj()) : NULL;
}

void LwpPieceManager::Read(LwpObjectStream *pStrm)
{
    m_GeometryPieceList.ReadIndexed(pStrm);
    m_ScalePieceList.ReadIndexed(pStrm);
    m_MarginsPieceList.ReadIndexed(pStrm);
    m_ColumnsPieceList.ReadIndexed(pStrm);
    m_BorderStuffPieceList.ReadIndexed(pStrm);

    m_GutterStuffPieceList.ReadIndexed(pStrm);
    m_BackgroundStuffPieceList.ReadIndexed(pStrm);
    m_JoinStuffPieceList.ReadIndexed(pStrm);
    m_ShadowPieceList.ReadIndexed(pStrm);
    m_NumericsPieceList.ReadIndexed(pStrm);

    m_RelativityPieceList.ReadIndexed(pStrm);
    m_AlignmentPieceList.ReadIndexed(pStrm);
    m_IndentPieceList.ReadIndexed(pStrm);
    m_ParaBorderPieceList.ReadIndexed(pStrm);
    m_SpacingPieceList.ReadIndexed(pStrm);

    m_BreaksPieceList.ReadIndexed(pStrm);
    m_NumberingPieceList.ReadIndexed(pStrm);
    m_TabPieceList.ReadIndexed(pStrm);
    m_CharacterBorderPieceList.ReadIndexed(pStrm);
    m_AmikakePieceList.ReadIndexed(pStrm);

    if(pStrm->CheckExtra())
    {
        m_ParaBackgroundPieceList.ReadIndexed(pStrm);
        m_ExternalBorderStuffPieceList.ReadIndexed(pStrm);
        m_ExternalJoinStuffPieceList.ReadIndexed(pStrm);
        pStrm->SkipExtra();
    }
}

void LwpOrderedObjectManager::Read(LwpObjectStream *pStrm)
{
    m_Head.ReadIndexed(pStrm);
}

/**
* @descr: 	Get next orderedobject, copy from lwp source code
*
*/
LwpOrderedObject* LwpOrderedObjectManager::Enumerate(LwpOrderedObject * pLast)
{
    // If Last has a next, return it.
    if(pLast && !pLast->GetNext()->IsNull())
        return static_cast<LwpOrderedObject*>(pLast->GetNext()->obj());

    LwpListList* pList = NULL;
    if(pLast)
    {
        // We're at the end of Last's list (not Liszt's list).
        // Start with the next active list
        pList = static_cast<LwpListList*>(pLast->GetListList()->obj());
        pList= GetNextActiveListList(pList);
    }
    else
    {
        // Start with the first active ListList
        pList = GetNextActiveListList(NULL);
    }

    if(pList)
    {
        return static_cast<LwpOrderedObject*>(pList->GetHead()->obj());
    }

    return NULL;
}

/**
* @descr: 	Get next listlist object, copy from lwp source code
*
*/
LwpListList* LwpOrderedObjectManager::GetNextActiveListList(LwpListList * pLast)
{
    LwpListList* pList = NULL;
    LwpContent* pContent = NULL;
    if(pLast)
        pList = static_cast<LwpListList*>(pLast->GetNext()->obj());
    else
    {
        LwpDLVListHeadHolder* pHeadHolder= static_cast<LwpDLVListHeadHolder*>(m_Head.obj());
        if(pHeadHolder)
        {
            pList = static_cast<LwpListList*>(pHeadHolder->GetHeadID()->obj());
        }
    }

    while(pList)
    {
        pContent = static_cast<LwpContent*>(pList->GetObject()->obj());
        if(pContent && pContent->HasNonEmbeddedLayouts() &&
            !pContent->IsStyleContent())
            return pList;
        pList = static_cast<LwpListList*>(pList->GetNext()->obj());
    }
    return NULL;
}

LwpStyleManager::LwpStyleManager()
{}

LwpStyleManager::~LwpStyleManager()
{
    m_StyleList.clear();
}


#include "xfilter/xfstylemanager.hxx"
/*
VO_PARASTYLE/VO_CHARACTERSTYLE call this method to add its created style to XFStyleManager
1. Add the style to XFStyleManager, and return the <office:styles> style name
2. Add it to LwpParaStyleMap.
Prerequisite: pStyle has been created and all properties has been set to it.
Return the XFStyle* added by XFStyleManager
*/
IXFStyle* LwpStyleManager::AddStyle(LwpObjectID styleObjID, IXFStyle* pStyle)
{
    assert(pStyle);
    //pStyle may change if same style is found in XFStyleManager
    XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
    pStyle = pXFStyleManager->AddStyle(pStyle);
    m_StyleList.insert(LwpStyleMap::value_type(styleObjID, pStyle));
    return pStyle;
}

/*
Called by VO_PARA  or other objects to get style name based on the Style object ID
1) Get style from LwpParaStyleMap based on the LwpObjectID of VO_PARASTYLE.
Prerequisite: VO_PARASTYLE/VO_CHARACTERSTYLE should call AddStyle first.
Return empty string if no style found.
*/
IXFStyle* LwpStyleManager::GetStyle(const LwpObjectID &styleObjID)
{
    LwpStyleMap::const_iterator it =  m_StyleList.find(styleObjID);
    if (it != m_StyleList.end()) {
        return((*it).second);
    }
    return NULL;
}

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