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

#include <drawinglayer/primitive2d/textbreakuphelper.hxx>
#include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx>
#include <com/sun/star/i18n/XBreakIterator.hpp>
#include <comphelper/processfactory.hxx>
#include <com/sun/star/i18n/CharacterIteratorMode.hdl>
#include <com/sun/star/i18n/WordType.hpp>
#include <com/sun/star/i18n/CharType.hpp>

//////////////////////////////////////////////////////////////////////////////

namespace drawinglayer
{
    namespace primitive2d
    {
        TextBreakupHelper::TextBreakupHelper(const TextSimplePortionPrimitive2D& rSource)
        :   mrSource(rSource),
            mxResult(),
            maTextLayouter(),
            maDecTrans(),
            mbNoDXArray(false)
        {
            OSL_ENSURE(dynamic_cast< const TextSimplePortionPrimitive2D* >(&mrSource), "TextBreakupHelper with illegal primitive created (!)");
            maDecTrans = mrSource.getTextTransform();
            mbNoDXArray = mrSource.getDXArray().empty();

            if(mbNoDXArray)
            {
                // init TextLayouter when no dxarray
                maTextLayouter.setFontAttribute(
                    mrSource.getFontAttribute(), 
                    maDecTrans.getScale().getX(), 
                    maDecTrans.getScale().getY(),
                    mrSource.getLocale());
            }
        }

        TextBreakupHelper::~TextBreakupHelper()
        {
        }

        void TextBreakupHelper::breakupPortion(Primitive2DVector& rTempResult, sal_uInt32 nIndex, sal_uInt32 nLength, bool bWordLineMode)
        {
            if(nLength && !(nIndex == mrSource.getTextPosition() && nLength == mrSource.getTextLength()))
            {
                // prepare values for new portion
                basegfx::B2DHomMatrix aNewTransform;
                ::std::vector< double > aNewDXArray;
                const bool bNewStartIsNotOldStart(nIndex > mrSource.getTextPosition());

                if(!mbNoDXArray)
                {
                    // prepare new DXArray for the single word
                    aNewDXArray = ::std::vector< double >(
                        mrSource.getDXArray().begin() + (nIndex - mrSource.getTextPosition()), 
                        mrSource.getDXArray().begin() + ((nIndex + nLength) - mrSource.getTextPosition()));
                }

                if(bNewStartIsNotOldStart)
                {
                    // needs to be moved to a new start position
                    double fOffset(0.0);

                    if(mbNoDXArray)
                    {
                        // evaluate using TextLayouter
                        fOffset = maTextLayouter.getTextWidth(mrSource.getText(), mrSource.getTextPosition(), nIndex);
                    }
                    else
                    {
                        // get from DXArray
                        const sal_uInt32 nIndex2(static_cast< sal_uInt32 >(nIndex - mrSource.getTextPosition()));
                        fOffset = mrSource.getDXArray()[nIndex2 - 1];
                    }

                    // need offset without FontScale for building the new transformation. The
                    // new transformation will be multiplied with the current text transformation
                    // so FontScale would be double
                    double fOffsetNoScale(fOffset);
                    const double fFontScaleX(maDecTrans.getScale().getX());

                    if(!basegfx::fTools::equal(fFontScaleX, 1.0) 
                        && !basegfx::fTools::equalZero(fFontScaleX))
                    {
                        fOffsetNoScale /= fFontScaleX;
                    }

                    // apply needed offset to transformation
                    aNewTransform.translate(fOffsetNoScale, 0.0);

                    if(!mbNoDXArray)
                    {
                        // DXArray values need to be corrected with the offset, too. Here,
                        // take the scaled offset since the DXArray is scaled
                        const sal_uInt32 nArraySize(aNewDXArray.size());

                        for(sal_uInt32 a(0); a < nArraySize; a++)
                        {
                            aNewDXArray[a] -= fOffset;
                        }
                    }
                }

                // add text transformation to new transformation
                aNewTransform = maDecTrans.getB2DHomMatrix() * aNewTransform;

                // callback to allow evtl. changes
                const bool bCreate(allowChange(rTempResult.size(), aNewTransform, nIndex, nLength));

                if(bCreate)
                {
                    // check if we have a decorated primitive as source
                    const TextDecoratedPortionPrimitive2D* pTextDecoratedPortionPrimitive2D = 
                        dynamic_cast< const TextDecoratedPortionPrimitive2D* >(&mrSource);

                    if(pTextDecoratedPortionPrimitive2D)
                    {
                        // create a TextDecoratedPortionPrimitive2D
                        rTempResult.push_back(
                            new TextDecoratedPortionPrimitive2D(
                                aNewTransform,
                                mrSource.getText(),
                                nIndex,
                                nLength,
                                aNewDXArray,
                                mrSource.getFontAttribute(),
                                mrSource.getLocale(),
                                mrSource.getFontColor(),
                            
                                pTextDecoratedPortionPrimitive2D->getOverlineColor(),
                                pTextDecoratedPortionPrimitive2D->getTextlineColor(),
                                pTextDecoratedPortionPrimitive2D->getFontOverline(),
                                pTextDecoratedPortionPrimitive2D->getFontUnderline(),
                                pTextDecoratedPortionPrimitive2D->getUnderlineAbove(),
                                pTextDecoratedPortionPrimitive2D->getTextStrikeout(),

                                // reset WordLineMode when BreakupUnit_word is executed; else copy original
                                bWordLineMode ? false : pTextDecoratedPortionPrimitive2D->getWordLineMode(),

                                pTextDecoratedPortionPrimitive2D->getTextEmphasisMark(),
                                pTextDecoratedPortionPrimitive2D->getEmphasisMarkAbove(),
                                pTextDecoratedPortionPrimitive2D->getEmphasisMarkBelow(),
                                pTextDecoratedPortionPrimitive2D->getTextRelief(),
                                pTextDecoratedPortionPrimitive2D->getShadow()));
                    }
                    else
                    {
                        // create a SimpleTextPrimitive
                        rTempResult.push_back(
                            new TextSimplePortionPrimitive2D(
                                aNewTransform,
                                mrSource.getText(),
                                nIndex,
                                nLength,
                                aNewDXArray,
                                mrSource.getFontAttribute(),
                                mrSource.getLocale(),
                                mrSource.getFontColor()));
                    }
                }
            }
        }

        bool TextBreakupHelper::allowChange(sal_uInt32 /*nCount*/, basegfx::B2DHomMatrix& /*rNewTransform*/, sal_uInt32 /*nIndex*/, sal_uInt32 /*nLength*/)
        {
            return true;
        }

        void TextBreakupHelper::breakup(BreakupUnit aBreakupUnit)
        {
            if(mrSource.getTextLength())
            {
                Primitive2DVector aTempResult;
                static ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XBreakIterator > xBreakIterator;

                if(!xBreakIterator.is())
                {
                    ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xMSF(::comphelper::getProcessServiceFactory());
                    xBreakIterator.set(xMSF->createInstance(rtl::OUString::createFromAscii("com.sun.star.i18n.BreakIterator")), ::com::sun::star::uno::UNO_QUERY);
                }

                if(xBreakIterator.is())
                {
                    const rtl::OUString& rTxt = mrSource.getText();
                    const sal_Int32 nTextLength(mrSource.getTextLength());
                    const ::com::sun::star::lang::Locale& rLocale = mrSource.getLocale();
                    const sal_Int32 nTextPosition(mrSource.getTextPosition());
                    sal_Int32 nCurrent(nTextPosition);
                    
                    switch(aBreakupUnit)
                    {
                        case BreakupUnit_character:
                        {
                            sal_Int32 nDone;
                            sal_Int32 nNextCellBreak(xBreakIterator->nextCharacters(rTxt, nTextPosition, rLocale, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL, 0, nDone));
                            sal_Int32 a(nTextPosition);

                            for(; a < nTextPosition + nTextLength; a++)
                            {
                                if(a == nNextCellBreak)
                                {
                                    breakupPortion(aTempResult, nCurrent, a - nCurrent, false);
                                    nCurrent = a;
                                    nNextCellBreak = xBreakIterator->nextCharacters(rTxt, a, rLocale, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL, 1, nDone);
                                }
                            }

                            breakupPortion(aTempResult, nCurrent, a - nCurrent, false);
                            break;
                        }
                        case BreakupUnit_word:
                        {
                            ::com::sun::star::i18n::Boundary nNextWordBoundary(xBreakIterator->getWordBoundary(rTxt, nTextPosition, rLocale, ::com::sun::star::i18n::WordType::ANY_WORD, sal_True));
                            sal_Int32 a(nTextPosition);
                            
                            for(; a < nTextPosition + nTextLength; a++)
                            {
                                if(a == nNextWordBoundary.endPos)
                                {
                                    if(a > nCurrent)
                                    {
                                        breakupPortion(aTempResult, nCurrent, a - nCurrent, true);
                                    }

                                    nCurrent = a;

                                    // skip spaces (maybe enhanced with a bool later if needed)
                                    {
                                        const sal_Int32 nEndOfSpaces(xBreakIterator->endOfCharBlock(rTxt, a, rLocale, ::com::sun::star::i18n::CharType::SPACE_SEPARATOR));

                                        if(nEndOfSpaces > a)
                                        {
                                            nCurrent = nEndOfSpaces;
                                        }
                                    }

                                    nNextWordBoundary = xBreakIterator->getWordBoundary(rTxt, a + 1, rLocale, ::com::sun::star::i18n::WordType::ANY_WORD, sal_True);
                                }
                            }

                            if(a > nCurrent)
                            {
                                breakupPortion(aTempResult, nCurrent, a - nCurrent, true);
                            }
                            break;
                        }
                        case BreakupUnit_sentence:
                        {
                            sal_Int32 nNextSentenceBreak(xBreakIterator->endOfSentence(rTxt, nTextPosition, rLocale));
                            sal_Int32 a(nTextPosition);
                            
                            for(; a < nTextPosition + nTextLength; a++)
                            {
                                if(a == nNextSentenceBreak)
                                {
                                    breakupPortion(aTempResult, nCurrent, a - nCurrent, false);
                                    nCurrent = a;
                                    nNextSentenceBreak = xBreakIterator->endOfSentence(rTxt, a + 1, rLocale);
                                }
                            }

                            breakupPortion(aTempResult, nCurrent, a - nCurrent, false);
                            break;
                        }
                    }
                }
                
                mxResult = Primitive2DVectorToPrimitive2DSequence(aTempResult);
            }
        }

        const Primitive2DSequence& TextBreakupHelper::getResult(BreakupUnit aBreakupUnit) const
        {
            if(!mxResult.hasElements())
            {
                const_cast< TextBreakupHelper* >(this)->breakup(aBreakupUnit);
            }

            return mxResult;
        }

    } // end of namespace primitive2d
} // end of namespace drawinglayer

//////////////////////////////////////////////////////////////////////////////
// eof
