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

#include "PresenterHelpView.hxx"
#include "PresenterButton.hxx"
#include "PresenterCanvasHelper.hxx"
#include "PresenterGeometryHelper.hxx"
#include "PresenterHelper.hxx"
#include "PresenterWindowManager.hxx"
#include <com/sun/star/awt/XWindowPeer.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/drawing/framework/XConfigurationController.hpp>
#include <com/sun/star/drawing/framework/XControllerManager.hpp>
#include <com/sun/star/rendering/CompositeOperation.hpp>
#include <com/sun/star/rendering/TextDirection.hpp>
#include <com/sun/star/util/Color.hpp>
#include <algorithm>
#include <vector>
#include <boost/bind.hpp>

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::drawing::framework;
using ::rtl::OUString;
using ::std::vector;

#define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString)))


namespace sdext { namespace presenter {

namespace {
    const static sal_Int32 gnHorizontalGap (20);
    const static sal_Int32 gnVerticalBorder (30);
    const static sal_Int32 gnVerticalButtonPadding (12);

    class LineDescriptor
    {
    public:
        LineDescriptor(void);
        void AddPart (
            const OUString& rsLine,
            const css::uno::Reference<css::rendering::XCanvasFont>& rxFont);
        bool IsEmpty (void) const;

        OUString msLine;
        geometry::RealSize2D maSize;
        double mnVerticalOffset;

        void CalculateSize (const css::uno::Reference<css::rendering::XCanvasFont>& rxFont);
    };

    class LineDescriptorList
    {
    public:
        LineDescriptorList (
            const OUString& rsText,
            const css::uno::Reference<css::rendering::XCanvasFont>& rxFont,
            const sal_Int32 nMaximalWidth);

        void Update (
            const css::uno::Reference<css::rendering::XCanvasFont>& rxFont,
            const sal_Int32 nMaximalWidth);

        double Paint(
            const Reference<rendering::XCanvas>& rxCanvas,
            const geometry::RealRectangle2D& rBBox,
            const bool bFlushLeft,
            const rendering::ViewState& rViewState,
            rendering::RenderState& rRenderState,
            const css::uno::Reference<css::rendering::XCanvasFont>& rxFont) const;
        double GetHeight (void) const;

    private:
        const OUString msText;
        ::boost::shared_ptr<vector<LineDescriptor> > mpLineDescriptors;

        void SplitText (const ::rtl::OUString& rsText, vector<rtl::OUString>& rTextParts);
        void FormatText (
            const vector<rtl::OUString>& rTextParts,
            const css::uno::Reference<css::rendering::XCanvasFont>& rxFont,
            const sal_Int32 nMaximalWidth);
    };

    class Block
    {
    public:
        Block (const Block& rBlock);
        Block (
            const OUString& rsLeftText,
            const OUString& rsRightText,
            const css::uno::Reference<css::rendering::XCanvasFont>& rxFont,
            const sal_Int32 nMaximalWidth);
        void Update (
            const css::uno::Reference<css::rendering::XCanvasFont>& rxFont,
            const sal_Int32 nMaximalWidth);

        LineDescriptorList maLeft;
        LineDescriptorList maRight;
    };
} // end of anonymous namespace

class PresenterHelpView::TextContainer : public vector<boost::shared_ptr<Block> >
{
};


PresenterHelpView::PresenterHelpView (
    const Reference<uno::XComponentContext>& rxContext,
    const Reference<XResourceId>& rxViewId,
    const Reference<frame::XController>& rxController,
    const ::rtl::Reference<PresenterController>& rpPresenterController)
    : PresenterHelpViewInterfaceBase(m_aMutex),
      mxComponentContext(rxContext),
      mxViewId(rxViewId),
      mxPane(),
      mxWindow(),
      mxCanvas(),
      mpPresenterController(rpPresenterController),
      mpFont(),
      mpTextContainer(),
      mpCloseButton(),
      mnSeparatorY(0),
      mnMaximalWidth(0)
{
    try
    {
        // Get the content window via the pane anchor.
        Reference<XControllerManager> xCM (rxController, UNO_QUERY_THROW);
        Reference<XConfigurationController> xCC (
            xCM->getConfigurationController(), UNO_QUERY_THROW);
        mxPane = Reference<XPane>(xCC->getResource(rxViewId->getAnchor()), UNO_QUERY_THROW);

        mxWindow = mxPane->getWindow();
        ProvideCanvas();

        mxWindow->addWindowListener(this);
        mxWindow->addPaintListener(this);
        Reference<awt::XWindowPeer> xPeer (mxWindow, UNO_QUERY);
        if (xPeer.is())
            xPeer->setBackground(util::Color(0xff000000));
        mxWindow->setVisible(sal_True);

        if (mpPresenterController.is())
        {
            mpFont = mpPresenterController->GetViewFont(mxViewId->getResourceURL());
            if (mpFont.get() != NULL)
            {
                mpFont->PrepareFont(mxCanvas);
            }
        }

        // Create the close button.
        mpCloseButton = PresenterButton::Create(
            mxComponentContext,
            mpPresenterController,
            mpPresenterController->GetTheme(),
            mxWindow,
            mxCanvas,
            A2S("HelpViewCloser"));

        ReadHelpStrings();
        Resize();
    }
    catch (RuntimeException&)
    {
        mxViewId = NULL;
        mxWindow = NULL;
        throw;
    }
}




PresenterHelpView::~PresenterHelpView (void)
{
}




void SAL_CALL PresenterHelpView::disposing (void)
{
    mxViewId = NULL;

    if (mpCloseButton.is())
    {
        Reference<lang::XComponent> xComponent (
            static_cast<XWeak*>(mpCloseButton.get()), UNO_QUERY);
        mpCloseButton = NULL;
        if (xComponent.is())
            xComponent->dispose();
    }

    if (mxWindow.is())
    {
        mxWindow->removeWindowListener(this);
        mxWindow->removePaintListener(this);
    }
}




//----- lang::XEventListener --------------------------------------------------

void SAL_CALL PresenterHelpView::disposing (const lang::EventObject& rEventObject)
    throw (RuntimeException)
{
    if (rEventObject.Source == mxCanvas)
    {
        mxCanvas = NULL;
    }
    else if (rEventObject.Source == mxWindow)
    {
        mxWindow = NULL;
        dispose();
    }
}




//----- XWindowListener -------------------------------------------------------

void SAL_CALL PresenterHelpView::windowResized (const awt::WindowEvent& rEvent)
    throw (uno::RuntimeException)
{
    (void)rEvent;
    ThrowIfDisposed();
    Resize();
}




void SAL_CALL PresenterHelpView::windowMoved (const awt::WindowEvent& rEvent)
    throw (uno::RuntimeException)
{
    (void)rEvent;
    ThrowIfDisposed();
}




void SAL_CALL PresenterHelpView::windowShown (const lang::EventObject& rEvent)
    throw (uno::RuntimeException)
{
    (void)rEvent;
    ThrowIfDisposed();
    Resize();
}




void SAL_CALL PresenterHelpView::windowHidden (const lang::EventObject& rEvent)
    throw (uno::RuntimeException)
{
    (void)rEvent;
    ThrowIfDisposed();
}




//----- XPaintListener --------------------------------------------------------

void SAL_CALL PresenterHelpView::windowPaint (const css::awt::PaintEvent& rEvent)
    throw (RuntimeException)
{
    Paint(rEvent.UpdateRect);
}




void PresenterHelpView::Paint (const awt::Rectangle& rUpdateBox)
{
    ProvideCanvas();
    if ( ! mxCanvas.is())
        return;

    // Clear background.
    const awt::Rectangle aWindowBox (mxWindow->getPosSize());
    mpPresenterController->GetCanvasHelper()->Paint(
        mpPresenterController->GetViewBackground(mxViewId->getResourceURL()),
        Reference<rendering::XCanvas>(mxCanvas, UNO_QUERY),
        rUpdateBox,
        awt::Rectangle(0,0,aWindowBox.Width,aWindowBox.Height),
        awt::Rectangle());

    // Paint vertical divider.

    rendering::ViewState aViewState(
        geometry::AffineMatrix2D(1,0,0, 0,1,0),
        PresenterGeometryHelper::CreatePolygon(rUpdateBox, mxCanvas->getDevice()));

    rendering::RenderState aRenderState (
        geometry::AffineMatrix2D(1,0,0, 0,1,0),
        NULL,
        Sequence<double>(4),
        rendering::CompositeOperation::SOURCE);
    PresenterCanvasHelper::SetDeviceColor(aRenderState, mpFont->mnColor);

    mxCanvas->drawLine(
        geometry::RealPoint2D(aWindowBox.Width/2, gnVerticalBorder),
        geometry::RealPoint2D(aWindowBox.Width/2, mnSeparatorY - gnVerticalBorder),
        aViewState,
        aRenderState);

    // Paint the horizontal separator.
    mxCanvas->drawLine(
        geometry::RealPoint2D(0, mnSeparatorY),
        geometry::RealPoint2D(aWindowBox.Width, mnSeparatorY),
        aViewState,
        aRenderState);

    // Paint text.
    double nY (gnVerticalBorder);
    TextContainer::const_iterator iBlock (mpTextContainer->begin());
    TextContainer::const_iterator iBlockEnd (mpTextContainer->end());
    for ( ; iBlock!=iBlockEnd; ++iBlock)
    {
        const double nLeftHeight (
            (*iBlock)->maLeft.Paint(mxCanvas,
                geometry::RealRectangle2D(
                    gnHorizontalGap,
                    nY,
                    aWindowBox.Width/2 - gnHorizontalGap,
                    aWindowBox.Height - gnVerticalBorder),
                false,
                aViewState,
                aRenderState,
                mpFont->mxFont));
        const double nRightHeight (
            (*iBlock)->maRight.Paint(mxCanvas,
                geometry::RealRectangle2D(
                    aWindowBox.Width/2 + gnHorizontalGap,
                    nY,
                    aWindowBox.Width - gnHorizontalGap,
                    aWindowBox.Height - gnVerticalBorder),
                true,
                aViewState,
                aRenderState,
                mpFont->mxFont));
        nY += ::std::max(nLeftHeight,nRightHeight);
    }

    Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
    if (xSpriteCanvas.is())
        xSpriteCanvas->updateScreen(sal_False);
}




void PresenterHelpView::ReadHelpStrings (void)
{
    mpTextContainer.reset(new TextContainer());
    PresenterConfigurationAccess aConfiguration (
        mxComponentContext,
        OUString::createFromAscii("/org.openoffice.Office.PresenterScreen/"),
        PresenterConfigurationAccess::READ_ONLY);
    Reference<container::XNameAccess> xStrings (
        aConfiguration.GetConfigurationNode(A2S("PresenterScreenSettings/HelpView/HelpStrings")),
        UNO_QUERY);
    PresenterConfigurationAccess::ForAll(
        xStrings,
        ::boost::bind(&PresenterHelpView::ProcessString, this, _2));
}




void PresenterHelpView::ProcessString (
    const Reference<beans::XPropertySet>& rsProperties)
{
    if ( ! rsProperties.is())
        return;

    OUString sLeftText;
    PresenterConfigurationAccess::GetProperty(rsProperties, A2S("Left")) >>= sLeftText;
    OUString sRightText;
    PresenterConfigurationAccess::GetProperty(rsProperties, A2S("Right")) >>= sRightText;

    const awt::Rectangle aWindowBox (mxWindow->getPosSize());
    mpTextContainer->push_back(
        ::boost::shared_ptr<Block>(
            new Block(sLeftText, sRightText, mpFont->mxFont, mnMaximalWidth)));
}




void PresenterHelpView::CheckFontSize (void)
{
    if (mpFont.get() == NULL)
        return;

    const awt::Rectangle aWindowBox (mxWindow->getPosSize());
    if (aWindowBox.Width<=0 || aWindowBox.Height<=0)
        return;

    sal_Int32 nBestSize (6);

    // Scaling down and then reformatting can cause the text to be too large
    // still.  So do this again and again until the text size is
    // small enough.  Restrict the number of loops.
    for (int nLoopCount=0; nLoopCount<5; ++nLoopCount)
    {
        double nY (gnVerticalBorder);
        TextContainer::iterator iBlock (mpTextContainer->begin());
        TextContainer::const_iterator iBlockEnd (mpTextContainer->end());
        for ( ; iBlock!=iBlockEnd; ++iBlock)
            nY += ::std::max(
                (*iBlock)->maLeft.GetHeight(),
                (*iBlock)->maRight.GetHeight());

        const double nHeightDifference (nY - (aWindowBox.Height-gnVerticalBorder));
        if (nHeightDifference <= 0 && nHeightDifference > -50)
        {
            // We have found a good font size that is large and leaves not
            // too much space below the help text.
            return;
        }

        // Font is too large.  Make it smaller.

        // Use a simple linear transformation to calculate initial guess of
        // a size that lets all help text be shown inside the window.
        const double nScale (double(aWindowBox.Height-gnVerticalBorder) / nY);
        if (nScale > 0.95 && nScale <1.05)
            break;

        sal_Int32 nFontSizeGuess (::std::max(sal_Int32(1),sal_Int32(mpFont->mnSize * nScale)));
        if (nHeightDifference<0 && mpFont->mnSize>nBestSize)
            nBestSize = mpFont->mnSize;
        mpFont->mnSize = nFontSizeGuess;
        mpFont->mxFont = NULL;
        mpFont->PrepareFont(mxCanvas);

        // Reformat blocks.
        for (iBlock=mpTextContainer->begin(); iBlock!=iBlockEnd; ++iBlock)
            (*iBlock)->Update(mpFont->mxFont, mnMaximalWidth);
    }

    if (nBestSize != mpFont->mnSize)
    {
        mpFont->mnSize = nBestSize;
        mpFont->mxFont = NULL;
        mpFont->PrepareFont(mxCanvas);

        // Reformat blocks.
        for (TextContainer::iterator
                 iBlock (mpTextContainer->begin()),
                 iEnd (mpTextContainer->end());
             iBlock!=iEnd;
             ++iBlock)
        {
            (*iBlock)->Update(mpFont->mxFont, mnMaximalWidth);
        }
    }
}




//----- XResourceId -----------------------------------------------------------

Reference<XResourceId> SAL_CALL PresenterHelpView::getResourceId (void)
    throw (RuntimeException)
{
    ThrowIfDisposed();
    return mxViewId;
}




sal_Bool SAL_CALL PresenterHelpView::isAnchorOnly (void)
    throw (RuntimeException)
{
    return false;
}




//-----------------------------------------------------------------------------

void PresenterHelpView::ProvideCanvas (void)
{
    if ( ! mxCanvas.is() && mxPane.is())
    {
        mxCanvas = mxPane->getCanvas();
        if ( ! mxCanvas.is())
            return;
        Reference<lang::XComponent> xComponent (mxCanvas, UNO_QUERY);
        if (xComponent.is())
            xComponent->addEventListener(static_cast<awt::XPaintListener*>(this));

        if (mpCloseButton.is())
            mpCloseButton->SetCanvas(mxCanvas, mxWindow);
    }
}




void PresenterHelpView::Resize (void)
{
    if (mpCloseButton.get() != NULL && mxWindow.is())
    {
        const awt::Rectangle aWindowBox (mxWindow->getPosSize());
        mnMaximalWidth = (mxWindow->getPosSize().Width - 4*gnHorizontalGap) / 2;

        // Place vertical separator.
        mnSeparatorY = aWindowBox.Height
            - mpCloseButton->GetSize().Height - gnVerticalButtonPadding;

        mpCloseButton->SetCenter(geometry::RealPoint2D(
            aWindowBox.Width/2,
            aWindowBox.Height - mpCloseButton->GetSize().Height/2));

        CheckFontSize();
    }
}




void PresenterHelpView::ThrowIfDisposed (void)
    throw (lang::DisposedException)
{
	if (rBHelper.bDisposed || rBHelper.bInDispose)
	{
        throw lang::DisposedException (
            OUString(RTL_CONSTASCII_USTRINGPARAM(
                "PresenterHelpView has been already disposed")),
            const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
    }
}




//===== LineDescritor =========================================================

namespace {

LineDescriptor::LineDescriptor (void)
    : msLine(),
      maSize(0,0),
      mnVerticalOffset(0)
{
}




void LineDescriptor::AddPart (
    const OUString& rsLine,
    const css::uno::Reference<css::rendering::XCanvasFont>& rxFont)
{
    msLine += rsLine;

    CalculateSize(rxFont);
}




bool LineDescriptor::IsEmpty (void) const
{
    return msLine.getLength()==0;
}




void LineDescriptor::CalculateSize (
    const css::uno::Reference<css::rendering::XCanvasFont>& rxFont)
{
    OSL_ASSERT(rxFont.is());

    rendering::StringContext aContext (msLine, 0, msLine.getLength());
    Reference<rendering::XTextLayout> xLayout (
        rxFont->createTextLayout(aContext, rendering::TextDirection::WEAK_LEFT_TO_RIGHT, 0));
    const geometry::RealRectangle2D aTextBBox (xLayout->queryTextBounds());
    maSize = css::geometry::RealSize2D(aTextBBox.X2 - aTextBBox.X1, aTextBBox.Y2 - aTextBBox.Y1);
    mnVerticalOffset = aTextBBox.Y2;
}

} // end of anonymous namespace




//===== LineDescriptorList ====================================================

namespace {

LineDescriptorList::LineDescriptorList (
    const OUString& rsText,
    const css::uno::Reference<css::rendering::XCanvasFont>& rxFont,
    const sal_Int32 nMaximalWidth)
    : msText(rsText)
{
    Update(rxFont, nMaximalWidth);
}




double LineDescriptorList::Paint(
    const Reference<rendering::XCanvas>& rxCanvas,
    const geometry::RealRectangle2D& rBBox,
    const bool bFlushLeft,
    const rendering::ViewState& rViewState,
    rendering::RenderState& rRenderState,
    const css::uno::Reference<css::rendering::XCanvasFont>& rxFont) const
{
    if ( ! rxCanvas.is())
        return 0;

    double nY (rBBox.Y1);
    vector<LineDescriptor>::const_iterator iLine (mpLineDescriptors->begin());
    vector<LineDescriptor>::const_iterator iEnd (mpLineDescriptors->end());
    for ( ; iLine!=iEnd; ++iLine)
    {
        double nX (rBBox.X1);
        if ( ! bFlushLeft)
            nX = rBBox.X2 - iLine->maSize.Width;
        rRenderState.AffineTransform.m02 = nX;
        rRenderState.AffineTransform.m12 = nY + iLine->maSize.Height - iLine->mnVerticalOffset;

        const rendering::StringContext aContext (iLine->msLine, 0, iLine->msLine.getLength());

        rxCanvas->drawText (
            aContext,
            rxFont,
            rViewState,
            rRenderState,
            rendering::TextDirection::WEAK_LEFT_TO_RIGHT);

        nY += iLine->maSize.Height * 1.2;
    }

    return nY - rBBox.Y1;
}




double LineDescriptorList::GetHeight (void) const
{
    double nHeight (0);
    vector<LineDescriptor>::const_iterator iLine (mpLineDescriptors->begin());
    vector<LineDescriptor>::const_iterator iEnd (mpLineDescriptors->end());
    for ( ; iLine!=iEnd; ++iLine)
        nHeight += iLine->maSize.Height * 1.2;

    return nHeight;
}




void LineDescriptorList::Update (
    const css::uno::Reference<css::rendering::XCanvasFont>& rxFont,
    const sal_Int32 nMaximalWidth)
{
    vector<OUString> aTextParts;
    SplitText(msText, aTextParts);
    FormatText(aTextParts, rxFont, nMaximalWidth);
}




void LineDescriptorList::SplitText (
    const OUString& rsText,
    vector<OUString>& rTextParts)
{
    const sal_Char cQuote ('\'');
    const sal_Char cSeparator (',');

    sal_Int32 nIndex (0);
    sal_Int32 nStart (0);
    sal_Int32 nLength (rsText.getLength());
    bool bIsQuoted (false);
    while (nIndex < nLength)
    {
        const sal_Int32 nQuoteIndex (rsText.indexOf(cQuote, nIndex));
        const sal_Int32 nSeparatorIndex (rsText.indexOf(cSeparator, nIndex));
        if (nQuoteIndex>=0 && (nSeparatorIndex==-1 || nQuoteIndex<nSeparatorIndex))
        {
            bIsQuoted = !bIsQuoted;
            nIndex = nQuoteIndex+1;
            continue;
        }

        const sal_Int32 nNextIndex = nSeparatorIndex;
        if (nNextIndex < 0)
        {
            break;
        }
        else if ( ! bIsQuoted)
        {
            rTextParts.push_back(rsText.copy(nStart, nNextIndex-nStart));
            nStart = nNextIndex + 1;
        }
        nIndex = nNextIndex+1;
    }
    if (nStart < nLength)
        rTextParts.push_back(rsText.copy(nStart, nLength-nStart));
}




void LineDescriptorList::FormatText (
    const vector<OUString>& rTextParts,
    const css::uno::Reference<css::rendering::XCanvasFont>& rxFont,
    const sal_Int32 nMaximalWidth)
{
    LineDescriptor aLineDescriptor;

    mpLineDescriptors.reset(new vector<LineDescriptor>());

    vector<OUString>::const_iterator iPart (rTextParts.begin());
    vector<OUString>::const_iterator iEnd (rTextParts.end());
    for ( ; iPart!=iEnd; ++iPart)
    {
        if (aLineDescriptor.IsEmpty())
        {
            // Avoid empty lines.
            aLineDescriptor.AddPart(*iPart, rxFont);
        }
        else if (PresenterCanvasHelper::GetTextSize(
            rxFont, aLineDescriptor.msLine+A2S(", ")+*iPart).Width > nMaximalWidth)
        {
            aLineDescriptor.AddPart(A2S(","), rxFont);
            mpLineDescriptors->push_back(aLineDescriptor);
            aLineDescriptor = LineDescriptor();
            aLineDescriptor.AddPart(*iPart, rxFont);
        }
        else
        {
            aLineDescriptor.AddPart(A2S(", ")+*iPart, rxFont);
        }
    }
    if ( ! aLineDescriptor.IsEmpty())
    {
        mpLineDescriptors->push_back(aLineDescriptor);
    }
}


} // end of anonymous namespace




//===== Block =================================================================

namespace {

Block::Block (
    const OUString& rsLeftText,
    const OUString& rsRightText,
    const css::uno::Reference<css::rendering::XCanvasFont>& rxFont,
    const sal_Int32 nMaximalWidth)
    : maLeft(rsLeftText, rxFont, nMaximalWidth),
      maRight(rsRightText, rxFont, nMaximalWidth)
{
}



void Block::Update (
    const css::uno::Reference<css::rendering::XCanvasFont>& rxFont,
    const sal_Int32 nMaximalWidth)
{
    maLeft.Update(rxFont, nMaximalWidth);
    maRight.Update(rxFont, nMaximalWidth);
}

} // end of anonymous namespace

} } // end of namespace ::sdext::presenter
