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

#include "cppuhelper/implbase2.hxx"
#include "cppuhelper/implementationentry.hxx"
#include "unotools/configmgr.hxx"
#include "comphelper/servicedecl.hxx"
#include "comphelper/unwrapargs.hxx"
#include "i18npool/mslangid.hxx"
#include "vcl/svapp.hxx"
#include "vcl/msgbox.hxx"
#include "toolkit/helper/vclunohelper.hxx"
#include "com/sun/star/lang/XServiceInfo.hpp"
#include "com/sun/star/task/XJobExecutor.hpp"
#include "svtools/svmedit.hxx"
#include "svl/lstner.hxx"
#include "svtools/xtextedt.hxx"
#include <vcl/scrbar.hxx>
#include "vcl/threadex.hxx"



#include "boost/bind.hpp"
#include "dp_gui_shared.hxx"
#include "license_dialog.hxx"
#include "dp_gui.hrc"

using namespace ::dp_misc;
namespace cssu = ::com::sun::star::uno;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using ::rtl::OUString;

namespace dp_gui {

class LicenseView : public MultiLineEdit, public SfxListener
{
    sal_Bool            mbEndReached;
    Link            maEndReachedHdl;
    Link            maScrolledHdl;

public:
    LicenseView( Window* pParent, const ResId& rResId );
    ~LicenseView();

    void ScrollDown( ScrollType eScroll );

    sal_Bool IsEndReached() const;
    sal_Bool EndReached() const { return mbEndReached; }
    void SetEndReached( sal_Bool bEnd ) { mbEndReached = bEnd; }

    void SetEndReachedHdl( const Link& rHdl )  { maEndReachedHdl = rHdl; }
    const Link& GetAutocompleteHdl() const { return maEndReachedHdl; }

    void SetScrolledHdl( const Link& rHdl )  { maScrolledHdl = rHdl; }
    const Link& GetScrolledHdl() const { return maScrolledHdl; }

    virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint );

protected:
    using MultiLineEdit::Notify;
};

struct LicenseDialogImpl : public ModalDialog
{   
	cssu::Reference<cssu::XComponentContext> m_xComponentContext;
	FixedText m_ftHead;
    FixedText m_ftBody1;
    FixedText m_ftBody1Txt;
    FixedText m_ftBody2;
    FixedText m_ftBody2Txt;
	FixedImage m_fiArrow1;
	FixedImage m_fiArrow2;
    LicenseView m_mlLicense;
    PushButton m_pbDown;
	FixedLine m_flBottom;
 
    OKButton m_acceptButton;
	CancelButton m_declineButton;

	DECL_LINK(PageDownHdl, PushButton*);
	DECL_LINK(ScrolledHdl, LicenseView*);
	DECL_LINK(EndReachedHdl, LicenseView*);

	bool m_bLicenseRead;

    virtual ~LicenseDialogImpl();

	LicenseDialogImpl(
        Window * pParent,
        css::uno::Reference< css::uno::XComponentContext > const & xContext,
        const ::rtl::OUString & sExtensionName,
		const ::rtl::OUString & sLicenseText);

	virtual void Activate();
    
};

LicenseView::LicenseView( Window* pParent, const ResId& rResId )
    : MultiLineEdit( pParent, rResId )
{
    SetLeftMargin( 5 );
    mbEndReached = IsEndReached();
    StartListening( *GetTextEngine() );
}

LicenseView::~LicenseView()
{
    maEndReachedHdl = Link();
    maScrolledHdl   = Link();
    EndListeningAll();
}

void LicenseView::ScrollDown( ScrollType eScroll )
{
    ScrollBar*  pScroll = GetVScrollBar();
    if ( pScroll )
        pScroll->DoScrollAction( eScroll );
}

sal_Bool LicenseView::IsEndReached() const
{
    sal_Bool bEndReached;

    ExtTextView*    pView = GetTextView();
    ExtTextEngine*  pEdit = GetTextEngine();
    sal_uLong           nHeight = pEdit->GetTextHeight();
    Size            aOutSize = pView->GetWindow()->GetOutputSizePixel();
    Point           aBottom( 0, aOutSize.Height() );

    if ( (sal_uLong) pView->GetDocPos( aBottom ).Y() >= nHeight - 1 )
        bEndReached = sal_True;
    else
        bEndReached = sal_False;

    return bEndReached;
}

void LicenseView::Notify( SfxBroadcaster&, const SfxHint& rHint )
{
    if ( rHint.IsA( TYPE(TextHint) ) )
    {
        sal_Bool    bLastVal = EndReached();
        sal_uLong   nId = ((const TextHint&)rHint).GetId();

        if ( nId == TEXT_HINT_PARAINSERTED )
        {
            if ( bLastVal )
                mbEndReached = IsEndReached();
        }
        else if ( nId == TEXT_HINT_VIEWSCROLLED )
        {
            if ( ! mbEndReached )
                mbEndReached = IsEndReached();
            maScrolledHdl.Call( this );
        }

        if ( EndReached() && !bLastVal )
        {
            maEndReachedHdl.Call( this );
        }
    }
}

//==============================================================================================================

LicenseDialogImpl::LicenseDialogImpl(
	Window * pParent,
	cssu::Reference< cssu::XComponentContext > const & xContext,
    const ::rtl::OUString & sExtensionName,
    const ::rtl::OUString & sLicenseText):
		ModalDialog(pParent, DpGuiResId(RID_DLG_LICENSE))
		,m_xComponentContext(xContext)
		,m_ftHead(this, DpGuiResId(FT_LICENSE_HEADER))
		,m_ftBody1(this, DpGuiResId(FT_LICENSE_BODY_1))
		,m_ftBody1Txt(this, DpGuiResId(FT_LICENSE_BODY_1_TXT))
		,m_ftBody2(this, DpGuiResId(FT_LICENSE_BODY_2))
		,m_ftBody2Txt(this, DpGuiResId(FT_LICENSE_BODY_2_TXT))
		,m_fiArrow1(this, DpGuiResId(FI_LICENSE_ARROW1))
		,m_fiArrow2(this, DpGuiResId(FI_LICENSE_ARROW2))
		,m_mlLicense(this, DpGuiResId(ML_LICENSE))
		,m_pbDown(this, DpGuiResId(PB_LICENSE_DOWN))
		,m_flBottom(this, DpGuiResId(FL_LICENSE))
		,m_acceptButton(this, DpGuiResId(BTN_LICENSE_ACCEPT))
		,m_declineButton(this, DpGuiResId(BTN_LICENSE_DECLINE))
		,m_bLicenseRead(false)

{

	if (GetSettings().GetStyleSettings().GetHighContrastMode())
    {
        // high contrast mode needs other images
        m_fiArrow1.SetImage(Image(DpGuiResId(IMG_LICENCE_ARROW_HC)));
        m_fiArrow2.SetImage(Image(DpGuiResId(IMG_LICENCE_ARROW_HC)));
	}

	FreeResource();

	m_acceptButton.SetUniqueId(UID_BTN_LICENSE_ACCEPT);
	m_fiArrow1.Show(true);
	m_fiArrow2.Show(false);
	m_mlLicense.SetText(sLicenseText);
    m_ftHead.SetText(m_ftHead.GetText() + OUString('\n') + sExtensionName);
	
	m_mlLicense.SetEndReachedHdl( LINK(this, LicenseDialogImpl, EndReachedHdl) );
	m_mlLicense.SetScrolledHdl( LINK(this, LicenseDialogImpl, ScrolledHdl) );
    m_pbDown.SetClickHdl( LINK(this, LicenseDialogImpl, PageDownHdl) );

	// We want a automatic repeating page down button
    WinBits aStyle = m_pbDown.GetStyle();
    aStyle |= WB_REPEAT;
    m_pbDown.SetStyle( aStyle );
}

LicenseDialogImpl::~LicenseDialogImpl()
{
}

void LicenseDialogImpl::Activate()
{
	if (!m_bLicenseRead)
	{
		//Only enable the scroll down button if the license text does not fit into the window
		if (m_mlLicense.IsEndReached())
		{
			m_pbDown.Disable();
			m_acceptButton.Enable();
			m_acceptButton.GrabFocus();
		}
		else
		{
			m_pbDown.Enable();
			m_pbDown.GrabFocus();
			m_acceptButton.Disable();
		}
	}
}

IMPL_LINK( LicenseDialogImpl, ScrolledHdl, LicenseView *, EMPTYARG )
{

	if (m_mlLicense.IsEndReached())
        m_pbDown.Disable();
	else
        m_pbDown.Enable();

    return 0;
}

IMPL_LINK( LicenseDialogImpl, PageDownHdl, PushButton *, EMPTYARG )
{
    m_mlLicense.ScrollDown( SCROLL_PAGEDOWN );
    return 0;
}

IMPL_LINK( LicenseDialogImpl, EndReachedHdl, LicenseView *, EMPTYARG )
{
    m_acceptButton.Enable();
	m_acceptButton.GrabFocus();
	m_fiArrow1.Show(false);
	m_fiArrow2.Show(true);
	m_bLicenseRead = true;
    return 0;
}

//=================================================================================




LicenseDialog::LicenseDialog( Sequence<Any> const& args,
                          Reference<XComponentContext> const& xComponentContext)
    : m_xComponentContext(xComponentContext)
{
    comphelper::unwrapArgs( args, m_parent, m_sExtensionName, m_sLicenseText );
}

// XExecutableDialog
//______________________________________________________________________________
void LicenseDialog::setTitle( OUString const & ) throw (RuntimeException)
{
 
}

//______________________________________________________________________________
sal_Int16 LicenseDialog::execute() throw (RuntimeException)
{
    return vcl::solarthread::syncExecute(
        boost::bind( &LicenseDialog::solar_execute, this));
}

sal_Int16 LicenseDialog::solar_execute()
{
	std::auto_ptr<LicenseDialogImpl> dlg(
        new LicenseDialogImpl(
            VCLUnoHelper::GetWindow(m_parent),
            m_xComponentContext, m_sExtensionName, m_sLicenseText));

    return dlg->Execute();
}

} // namespace dp_gui

