/**************************************************************
 * 
 * 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 <stdio.h>
#include "Dff.hxx"
#include <doctok/resourceids.hxx>
#include <resourcemodel/WW8ResourceModel.hxx>
#include "resources.hxx"

namespace writerfilter {
namespace doctok {

typedef boost::shared_ptr<WW8Value> WW8ValueSharedPointer_t;

DffRecord::DffRecord(WW8Stream & rStream, sal_uInt32 nOffset, 
                     sal_uInt32 nCount)
: WW8StructBase(rStream, nOffset, nCount), bInitialized(false)
{
}

DffRecord::DffRecord(WW8StructBase * pParent, sal_uInt32 nOffset, 
                     sal_uInt32 nCount)
: WW8StructBase(pParent, nOffset, nCount), bInitialized(false)
{
}

Records_t::iterator DffRecord::begin()
{
    if (! bInitialized)
        initChildren();

    return mRecords.begin();
}

Records_t::iterator DffRecord::end()
{
    if (! bInitialized)
        initChildren();

    return mRecords.end();
}

bool DffRecord::isContainer() const
{
    return getVersion() == 0xf;
}

sal_uInt32 DffRecord::calcSize() const
{
    sal_uInt32 nResult = 0;

    switch (getRecordType())
    {
    case 0xf000:
    case 0xf001:
    case 0xf002:
    case 0xf003:
    case 0xf004:
        nResult = getU32(0x4) + 8;
        
        break;
    case 0xf700:
        nResult = 8;

        break;
    default:
        nResult = getU32(0x4);

        if (! isContainer())
            nResult += 8;
        break;
    }

    return nResult;
}

sal_uInt32 DffRecord::getVersion() const
{
    return getU8(0x0) & 0xf;
}

sal_uInt32 DffRecord::getInstance() const
{
    return (getU16(0x0) & 0xfff0) >> 4;
}

sal_uInt32 DffRecord::getRecordType() const
{
    return getU16(0x2);
}

void DffRecord::initChildren()
{
    if (isContainer())
    {
        sal_uInt32 nOffset = 8;
        sal_uInt32 nCount = calcSize();
        
        while (nCount - nOffset >= 8)
        {
            sal_uInt32 nSize = 0;
            boost::shared_ptr<DffRecord> pRec
                (createDffRecord(this, nOffset, &nSize));

            if (nSize == 0)
                break;
            
            mRecords.push_back(pRec);
            
            nOffset += nSize;
        }
    }

    bInitialized = true;
}

Records_t DffRecord::findRecords(sal_uInt32 nType, bool bRecursive, bool bAny)
{
    Records_t aResult;

    findRecords(nType, aResult, bRecursive, bAny);

    return aResult;
}

void DffRecord::findRecords
(sal_uInt32 nType, Records_t & rRecords, bool bRecursive, bool bAny)
{
    Records_t::iterator aIt = begin();

    while (aIt != end())
    {
        Pointer_t pPointer = *aIt;
        if (bAny || pPointer->getRecordType() == nType) 
            rRecords.push_back(pPointer);

        if (bRecursive)
            pPointer->findRecords(nType, rRecords, bRecursive, 
                                      bAny);

        ++aIt;
    }
}

void DffRecord::resolveChildren(Properties & rHandler)
{
    Records_t::iterator aIt;
    for (aIt = begin(); aIt != end(); ++aIt)
    {
        rHandler.sprm(**aIt);
    }
}

void DffRecord::resolveLocal(Properties &)
{
}

void DffRecord::resolve(Properties & rHandler)
{
    WW8Value::Pointer_t pVal = createValue(getRecordType());
    rHandler.attribute(NS_rtf::LN_dfftype, *pVal);

    pVal = createValue(getInstance());
    rHandler.attribute(NS_rtf::LN_dffinstance, *pVal);

    pVal = createValue(getVersion());
    rHandler.attribute(NS_rtf::LN_dffversion, *pVal);

    pVal = createValue(getU32(0x0));
    rHandler.attribute(NS_rtf::LN_dffheader, *pVal);
        
    if (isContainer())
    {
        resolveChildren(rHandler);
    }

    resolveLocal(rHandler);

#if 1
    WW8BinaryObjReference::Pointer_t pBinObjRef
        (new WW8BinaryObjReference(this, 0, getCount()));
    WW8Sprm aSprm(pBinObjRef);

    rHandler.sprm(aSprm);
#endif
}

sal_uInt32 DffRecord::getShapeType()
{
    sal_uInt32 nResult = 0;

    Records_t aRecords = findRecords(0xf00a);

    if (aRecords.size() > 0)
    {
        DffFSP * pDffFSP = dynamic_cast<DffFSP*>((*aRecords.begin()).get());
        nResult = pDffFSP->get_shptype();
    }

    return nResult;
}

sal_uInt32 DffRecord::getShapeId()
{
    sal_uInt32 nResult = 0;

    Records_t aRecords = findRecords(0xf00a);

    if (aRecords.size() > 0)
    {
        DffFSP * pDffFSP = dynamic_cast<DffFSP*>((*aRecords.begin()).get());
        nResult = pDffFSP->get_shpid();
    }

    return nResult;
}

class DffOPTHandler : public Properties
{
    map<int, WW8ValueSharedPointer_t> mMap;
    int nId;

public:
    DffOPTHandler() : nId(0) {}
    virtual ~DffOPTHandler() {}

    virtual void attribute(Id name, Value & val)
    {
        switch (name)
        {
        case NS_rtf::LN_shppid:
            nId = val.getInt();
            break;
        case NS_rtf::LN_shpvalue:
            {
                WW8Value & rTmpVal = dynamic_cast<WW8Value &>(val);
                WW8ValueSharedPointer_t 
                    pVal(dynamic_cast<WW8Value *>(rTmpVal.clone()));
                mMap[nId] = pVal;
            }
        }
    }

    virtual void sprm(Sprm & /*sprm_*/)
    {
    }

    WW8ValueSharedPointer_t & getValue(int nId_)
    {
        return mMap[nId_];
    }

};

sal_uInt32 DffRecord::getShapeBid()
{
    sal_uInt32 nResult = 0;

    if (getShapeType() == 75)
    {
        Records_t aRecords = findRecords(0xf00b);

        if (aRecords.size() > 0)
        {
            DffOPTHandler aHandler;
            DffOPT * pOpts = dynamic_cast<DffOPT*>((*aRecords.begin()).get());

            sal_uInt32 nCount = pOpts->get_property_count();

            for (sal_uInt32 n = 0; n < nCount; ++n)
            {
                pOpts->get_property(n)->resolve(aHandler);
            }

            WW8ValueSharedPointer_t pVal = aHandler.getValue(260);

            if (pVal.get() != NULL)
                nResult = pVal->getInt();
        }
    }
        
    return nResult;
}

string DffRecord::getType() const
{
    return "DffRecord";
}

Value::Pointer_t DffRecord::getValue()
{
    return Value::Pointer_t();
}

writerfilter::Reference<BinaryObj>::Pointer_t DffRecord::getBinary()
{
    return writerfilter::Reference<BinaryObj>::Pointer_t();
}

writerfilter::Reference<Stream>::Pointer_t DffRecord::getStream()
{
    return writerfilter::Reference<Stream>::Pointer_t();
}

writerfilter::Reference<Properties>::Pointer_t DffRecord::getProps()
{
    return writerfilter::Reference<Properties>::Pointer_t(this->clone());
}

string DffRecord::toString() const
{
    char sBuffer[1024];

    snprintf(sBuffer, sizeof(sBuffer), 
             "<dffrecord type=\"%" SAL_PRIuUINT32 "\" instance=\"%" SAL_PRIuUINT32 "\" version=\"%" SAL_PRIuUINT32 "\">\n",
             getRecordType(), getInstance(), getVersion());
    string aResult = sBuffer;
   

    if (!isContainer())
        aResult += mSequence.toString();
    else
    {
        WW8StructBase::Sequence aSeq(mSequence, 0, 8);
        aResult += aSeq.toString();
    }

    aResult += "</dffrecord>";

    return aResult;
}

string DffRecord::getName() const
{
    return "";
}

Sprm::Kind DffRecord::getKind()
{
    return Sprm::UNKNOWN;
}

DffBlock::DffBlock(WW8Stream & rStream, sal_uInt32 nOffset, 
                   sal_uInt32 nCount, sal_uInt32 nPadding)
: WW8StructBase(rStream, nOffset, nCount), bInitialized(false),
  mnPadding(nPadding)
{
}

DffBlock::DffBlock(WW8StructBase * pParent, sal_uInt32 nOffset, 
                   sal_uInt32 nCount, sal_uInt32 nPadding)
: WW8StructBase(pParent, nOffset, nCount), bInitialized(false), 
  mnPadding(nPadding)
{
}

DffBlock::DffBlock(const DffBlock & rSrc)
: WW8StructBase(rSrc), writerfilter::Reference<Properties>(rSrc), 
  bInitialized(false), mnPadding(rSrc.mnPadding)
{
}

void DffBlock::initChildren()
{
    sal_uInt32 nOffset = 0;
    sal_uInt32 nCount = getCount();
    
    while (nOffset < nCount)
    {
        sal_uInt32 nSize = 0;
        DffRecord::Pointer_t pDffRecord
            (createDffRecord(this, nOffset, &nSize));

        if (nSize == 0)
            break;

        mRecords.push_back(pDffRecord);
        
        nOffset +=  nSize + mnPadding;
    }    

    bInitialized = true;
}

Records_t DffBlock::findRecords(sal_uInt32 nType, bool bRecursive, bool bAny)
{
    Records_t aResult;

    findRecords(nType, aResult, bRecursive, bAny);

    return aResult;
}

void DffBlock::findRecords
(sal_uInt32 nType, Records_t & rRecords, bool bRecursive, bool bAny)
{
    Records_t::iterator aIt = begin();

    while (aIt != end())
    {
        DffRecord::Pointer_t pPointer(*aIt);

        if (bAny || pPointer->getRecordType() == nType)
            rRecords.push_back(pPointer);

        if (bRecursive)
            pPointer->findRecords(nType, rRecords, bRecursive, 
                                  bAny);
        
        ++aIt;
    }
}

void DffBlock::resolve(Properties & rHandler)
{
    Records_t::iterator aIt;

    for (aIt = begin(); aIt != end(); ++aIt)
    {
        DffRecord * pDff = aIt->get();
        rHandler.sprm(*pDff);
    }
}

DffRecord::Pointer_t DffBlock::getShape(sal_uInt32 nSpid)
{
    DffRecord::Pointer_t pResult;

    Records_t aRecords = findRecords(0xf004);
    Records_t::iterator aIt;
    for (aIt = aRecords.begin(); aIt != aRecords.end(); ++aIt)
    {
        DffRecord::Pointer_t pPointer = *aIt;

        Records_t aFSPs = pPointer->findRecords(0xf00a);
        Records_t::iterator aItFSP = aFSPs.begin();
        
        if (aItFSP != aFSPs.end())
        {
            DffFSP * pFSP = dynamic_cast<DffFSP *>((*aItFSP).get());

            if (pFSP->get_shpid() == nSpid)
            {
                pResult = pPointer;

                break;
            }
        }
    }

    return pResult;
}

DffRecord::Pointer_t DffBlock::getBlip(sal_uInt32 nBlip)
{
    DffRecord::Pointer_t pResult;

    if (nBlip > 0)
    {
        nBlip--;

        Records_t aRecords = findRecords(0xf007);
        
        if (nBlip < aRecords.size())
        {
            pResult = aRecords[nBlip];
        }
    }

    return pResult;
}

Records_t::iterator DffBlock::begin()
{
    if (! bInitialized)
        initChildren();

    return mRecords.begin();
}

Records_t::iterator DffBlock::end()
{
    if (! bInitialized)
        initChildren();

    return mRecords.end();
}

string DffBlock::getType() const
{
    return "DffBlock";
}

}}
