/**************************************************************
 *
 * 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 "informationdialog.hxx"
#include "optimizationstats.hxx"
#include "minimizer.hrc"
#include "helpid.hrc"

#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
#include <com/sun/star/awt/XUnitConversion.hpp>
#include <com/sun/star/graphic/XGraphicProvider.hpp>
#include <com/sun/star/graphic/XGraphic.hpp>
#include <com/sun/star/graphic/GraphicType.hpp>
#include <rtl/ustrbuf.hxx>
#include "com/sun/star/util/URL.hpp"
#include "com/sun/star/util/XURLTransformer.hpp"
#include <com/sun/star/util/MeasureUnit.hpp>
#include <com/sun/star/awt/PosSize.hpp>

#define DIALOG_WIDTH	240
#define DIALOG_HEIGHT	80
#define PAGE_POS_X		35
#define PAGE_WIDTH		( DIALOG_WIDTH - PAGE_POS_X ) - 6


// ---------------------
// - INFORMATIONDIALOG -
// ---------------------

using namespace ::com::sun::star;
using namespace ::com::sun::star::io;
using namespace ::com::sun::star::ui;
using namespace ::com::sun::star::awt;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::util;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::frame;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::script;
using namespace ::com::sun::star::container;

using ::rtl::OUString;

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

Reference< XFixedText > InformationDialog::InsertFixedText(
    const rtl::OUString& rControlName,
    const OUString& rLabel,
    sal_Int32 nXPos,
    sal_Int32 nYPos,
    sal_Int32 nWidth,
    sal_Int32 nHeight,
    sal_Bool bMultiLine,
    sal_Int16 nTabIndex )
{
	OUString pNames[] = {
		TKGet( TK_Height ),
		TKGet( TK_Label ),
		TKGet( TK_MultiLine ),
		TKGet( TK_PositionX ),
		TKGet( TK_PositionY ),
		TKGet( TK_Step ),
		TKGet( TK_TabIndex ),
		TKGet( TK_Width ) };

	Any	pValues[] = {
		Any( nHeight ),
		Any( rLabel ),
		Any( bMultiLine ),
		Any( nXPos ),
		Any( nYPos ),
		Any( (sal_Int16)0 ),
		Any( nTabIndex ),
		Any( nWidth ) };

	sal_Int32 nCount = sizeof( pNames ) / sizeof( OUString );

	Sequence< rtl::OUString >	aNames( pNames, nCount );
	Sequence< Any >				aValues( pValues, nCount );

    return insertFixedText( rControlName, aNames, aValues );
}

Reference< XControl > InformationDialog::InsertImage(
    const OUString& rControlName,
    const OUString& rURL,
    sal_Int32 nPosX,
    sal_Int32 nPosY,
    sal_Int32 nWidth,
    sal_Int32 nHeight,
    sal_Bool bScale )
{
	OUString pNames[] = {
		TKGet( TK_Border ),
		TKGet( TK_Height ),
		TKGet( TK_ImageURL ),
		TKGet( TK_PositionX ),
		TKGet( TK_PositionY ),
		TKGet( TK_ScaleImage ),
		TKGet( TK_Width ) };

	Any	pValues[] = {
		Any( sal_Int16( 0 ) ),
		Any( nHeight ),
		Any( rURL ),
		Any( nPosX ),
		Any( nPosY ),
		Any( bScale ),
		Any( nWidth ) };
	sal_Int32 nCount = sizeof( pNames ) / sizeof( OUString );

	Sequence< rtl::OUString >	aNames( pNames, nCount );
	Sequence< Any >				aValues( pValues, nCount );

	return insertImage( rControlName, aNames, aValues );
}

Reference< XCheckBox > InformationDialog::InsertCheckBox(
    const OUString& rControlName,
    const OUString& rLabel,
    const OUString& rHelpURL,
    sal_Int32 nXPos,
    sal_Int32 nYPos,
    sal_Int32 nWidth,
    sal_Int32 nHeight,
    sal_Int16 nTabIndex )
{
	OUString pNames[] = {
		TKGet( TK_Enabled ),
		TKGet( TK_Height ),
        TKGet( TK_HelpURL ),
		TKGet( TK_Label ),
		TKGet( TK_PositionX ),
		TKGet( TK_PositionY ),
		TKGet( TK_Step ),
		TKGet( TK_TabIndex ),
		TKGet( TK_Width ) };

	Any	pValues[] = {
		Any( sal_True ),
		Any( nHeight ),
        Any( rHelpURL ),
		Any( rLabel ),
		Any( nXPos ),
		Any( nYPos ),
		Any( (sal_Int16)0 ),
		Any( nTabIndex ),
		Any( nWidth ) };

	sal_Int32 nCount = sizeof( pNames ) / sizeof( OUString );

	Sequence< rtl::OUString >	aNames( pNames, nCount );
	Sequence< Any >				aValues( pValues, nCount );

	return insertCheckBox( rControlName, aNames, aValues );
}

Reference< XButton > InformationDialog::InsertButton(
    const OUString& rControlName,
    sal_Int32 nXPos,
    sal_Int32 nYPos,
    sal_Int32 nWidth,
    sal_Int32 nHeight,
    sal_Int16 nTabIndex,
    sal_Int32 nResID )
{
	OUString pNames[] = {
		TKGet( TK_Enabled ),
		TKGet( TK_Height ),
		TKGet( TK_Label ),
		TKGet( TK_PositionX ),
		TKGet( TK_PositionY ),
		TKGet( TK_PushButtonType ),
		TKGet( TK_Step ),
		TKGet( TK_TabIndex ),
		TKGet( TK_Width ) };

	Any	pValues[] = {
		Any( sal_True ),
		Any( nHeight ),
		Any( getString( nResID ) ),
		Any( nXPos ),
		Any( nYPos ),
		Any( static_cast< sal_Int16 >( PushButtonType_OK ) ),
		Any( (sal_Int16)0 ),
		Any( nTabIndex ),
		Any( nWidth ) };


	sal_Int32 nCount = sizeof( pNames ) / sizeof( OUString );

	Sequence< rtl::OUString >	aNames( pNames, nCount );
	Sequence< Any >				aValues( pValues, nCount );

	return insertButton( rControlName, Reference< XActionListener >(), aNames, aValues );
}


static OUString ImpValueOfInMB( const sal_Int64& rVal )
{
	double fVal( static_cast<double>( rVal ) );
	fVal /= ( 1 << 20 );
	fVal += 0.05;
	rtl::OUStringBuffer aVal( OUString::valueOf( fVal ) );
	sal_Int32 nX( OUString( aVal.getStr() ).indexOf( '.', 0 ) );
	if ( nX > 0 )
		aVal.setLength( nX + 2 );
	return aVal.makeStringAndClear();
}

void InformationDialog::InitDialog()
{
	sal_Int32 nDialogHeight = DIALOG_HEIGHT;
	if ( !maSaveAsURL.getLength() )
		nDialogHeight -= 22;

   // setting the dialog properties
	OUString pNames[] = {
		TKGet( TK_Closeable ),
		TKGet( TK_Height ),
        TKGet( TK_HelpURL ),
		TKGet( TK_Moveable ),
		TKGet( TK_PositionX ),
		TKGet( TK_PositionY ),
		TKGet( TK_Title ),
		TKGet( TK_Width ) };

	Any	pValues[] = {
		Any( sal_True ),
		Any( nDialogHeight ),
		Any( HID( HID_SDEXT_MINIMIZER_INFOBOX_DLG ) ),
		Any( sal_True ),
		Any( sal_Int32( 245 ) ),
		Any( sal_Int32( 115 ) ),
		Any( getString( STR_INFO_DIALOG ) ),
		Any( sal_Int32( DIALOG_WIDTH ) ) };

	sal_Int32 nCount = sizeof( pNames ) / sizeof( OUString );

	Sequence< rtl::OUString >	aNames( pNames, nCount );
	Sequence< Any >				aValues( pValues, nCount );

	mxDialogModelMultiPropertySet->setPropertyValues( aNames, aValues );

	sal_Int64 nSource = mnSourceSize;
	sal_Int64 nDest   = mnDestSize;

	sal_Int32 nInfoStrResId( STR_INFO_1 );
	if ( mnSourceSize )
	{
		if ( mnDestSize )
			nInfoStrResId = STR_INFO_1;
		else
		{
			nInfoStrResId = STR_INFO_2;
			nDest = mnApproxSize;
		}
	}
	else if ( mnDestSize )
		nInfoStrResId = STR_INFO_3;
	else
	{
		nInfoStrResId = STR_INFO_4;
		nDest = mnApproxSize;
	}

	rtl::OUString aTitle;
	if ( maSaveAsURL.getLength() )
	{
		Reference< XURLTransformer > xURLTransformer( mxContext->getServiceManager()->createInstanceWithContext(
				OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.util.URLTransformer" ) ), mxContext ), UNO_QUERY );
		if ( xURLTransformer.is() )
		{
			util::URL aURL, aPresentationURL;
			aURL.Complete = maSaveAsURL;
			xURLTransformer->parseSmart( aURL, rtl::OUString() );

			const OUString sFileProtocol( RTL_CONSTASCII_USTRINGPARAM( "file:///" ) );
			aPresentationURL.Complete = sFileProtocol.concat( aURL.Name );
			aTitle = xURLTransformer->getPresentation( aPresentationURL, sal_False );

			if ( aTitle.match( sFileProtocol, 0 ) )
				aTitle = aTitle.replaceAt( 0, sFileProtocol.getLength(), rtl::OUString() );
		}
	}

	OUString aInfoString( getString( nInfoStrResId ) );
	const OUString aOldSizePlaceholder( RTL_CONSTASCII_USTRINGPARAM( "%OLDFILESIZE" ) );
	const OUString aNewSizePlaceholder( RTL_CONSTASCII_USTRINGPARAM( "%NEWFILESIZE" ) );
	const OUString aTitlePlaceholder( aTitle.getLength() ? OUString::createFromAscii( "%TITLE" ) : OUString::createFromAscii( "'%TITLE'" ) );

	sal_Int32 i = aInfoString.indexOf( aOldSizePlaceholder, 0 );
	if ( i >= 0 )
		aInfoString = aInfoString.replaceAt( i, aOldSizePlaceholder.getLength(), ImpValueOfInMB( nSource ) );

	sal_Int32 j = aInfoString.indexOf( aNewSizePlaceholder, 0 );
	if ( j >= 0 )
		aInfoString = aInfoString.replaceAt( j, aNewSizePlaceholder.getLength(), ImpValueOfInMB( nDest ) );

	sal_Int32 k = aInfoString.indexOf( aTitlePlaceholder, 0 );
	if ( k >= 0 )
		aInfoString = aInfoString.replaceAt( k, aTitlePlaceholder.getLength(), aTitle );


    Reference< XControl > xImageCtrl = InsertImage( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "aboutimage" ) ),
                 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "private:standardimage/query" ) ),
                 3, 3, 25, 25, sal_False );
	Reference< XControl > xFixedText( InsertFixedText( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "fixedtext" ) ), aInfoString, PAGE_POS_X, 6, PAGE_WIDTH, 24, sal_True, 0 ), UNO_QUERY);

	if ( maSaveAsURL.getLength() )
        mxCheckBox = InsertCheckBox( TKGet( TK_OpenNewDocument ),
                                     getString( STR_AUTOMATICALLY_OPEN ),
                                     HID( HID_SDEXT_MINIMIZER_INFOBOX_CB_OPENNEW ),
                                     PAGE_POS_X, 42,
                                     PAGE_WIDTH, 8, 1 );
    Reference< XControl> xButtonCtrl( InsertButton( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "button" ) ), DIALOG_WIDTH / 2 - 15, nDialogHeight - 20, 30, 14, 2, STR_OK ), UNO_QUERY );

	sal_Bool bOpenNewDocument = mrbOpenNewDocument;
	setControlProperty( TKGet( TK_OpenNewDocument ), TKGet( TK_State ), Any( (sal_Int16)bOpenNewDocument ) );

    sal_Int32 nX, nY, nDlgWidth;
    Size aSize3( 3, 3 );
    Reference< XUnitConversion > xUnitConverter( mxDialogWindow, UNO_QUERY_THROW );
    aSize3 = xUnitConverter->convertSizeToPixel( aSize3, util::MeasureUnit::APPFONT );
    nX = nY = aSize3.Width;

    Reference< XPropertySet > xImageProps (xImageCtrl->getModel(), UNO_QUERY_THROW );
    Reference< graphic::XGraphic > xGraphic(
        xImageProps->getPropertyValue(
            OUString( RTL_CONSTASCII_USTRINGPARAM( "Graphic") ) ), UNO_QUERY_THROW );
    if ( xGraphic.is() && xGraphic->getType() != graphic::GraphicType::EMPTY )
    {
        Size aSizePixel;
        Rectangle aPosSizePixel;
        Reference< XPropertySet > xGraphicProps( xGraphic, UNO_QUERY_THROW );
        xGraphicProps->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("SizePixel"))) >>= aSizePixel;
        Reference< XWindow > xImage (xImageCtrl->getPeer(), UNO_QUERY_THROW );

        xImage->setPosSize( nX, nY,
                            aSizePixel.Width,
                            aSizePixel.Height,
                            awt::PosSize::POSSIZE );

        nX += aSizePixel.Width + aSize3.Width;

        Reference< XWindow > xLabel ( xFixedText->getPeer(), UNO_QUERY_THROW );
        aPosSizePixel = xLabel->getPosSize();
        xLabel->setPosSize( nX, nY,
                            aPosSizePixel.Width,
                            aPosSizePixel.Height,
                            awt::PosSize::POSSIZE );

        nDlgWidth = nX + aPosSizePixel.Width + aSize3.Width;
        nY += aPosSizePixel.Height + aSize3.Height;

        if ( mxCheckBox.is() )
        {
            Reference< XControl > xCheckBoxCtrl( mxCheckBox, UNO_QUERY_THROW );
            Reference< XWindow > xCheckBox( xCheckBoxCtrl->getPeer(), UNO_QUERY_THROW );
            Rectangle aCBSize = xCheckBox->getPosSize();
            xCheckBox->setPosSize( nX, nY,
                                   aPosSizePixel.Width,
                                   aCBSize.Height ,
                                   awt::PosSize::POSSIZE);
            nY += aCBSize.Height + aSize3.Height;
        }

        nY += aSize3.Height;
        Reference< XWindow > xButton ( xButtonCtrl->getPeer(), UNO_QUERY_THROW );
        aPosSizePixel = xButton->getPosSize();
        xButton->setPosSize( nDlgWidth / 2 - aPosSizePixel.Width / 2,
                             nY ,
                             aPosSizePixel.Width,
                             aPosSizePixel.Height,
                             awt::PosSize::POSSIZE );
        nY += aPosSizePixel.Height + aSize3.Height;
        mxDialogWindow->setPosSize( 0, 0, nDlgWidth, nY, awt::PosSize::SIZE );
    }

    centerDialog();
}

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

InformationDialog::InformationDialog(
    const Reference< XComponentContext > &rxContext,
    const Reference< XWindowPeer>& rxParent,
    const rtl::OUString& rSaveAsURL,
    sal_Bool& rbOpenNewDocument,
    const sal_Int64& rSourceSize,
    const sal_Int64& rDestSize,
    const sal_Int64& rApproxSize )
:   UnoDialog( rxContext, rxParent ),
	ConfigurationAccess( rxContext, NULL ),
	mxContext( rxContext ),
	mnSourceSize( rSourceSize ),
	mnDestSize( rDestSize ),
	mnApproxSize( rApproxSize ),
	mrbOpenNewDocument( rbOpenNewDocument ),
	maSaveAsURL( rSaveAsURL )
{
    OSL_TRACE( "InformationDialog::InformationDialog" );
	createWindowPeer();

	InitDialog();
}

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

InformationDialog::~InformationDialog()
{
    OSL_TRACE( "InformationDialog::~InformationDialog" );
}

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

sal_Bool InformationDialog::execute()
{
    OSL_TRACE( "InformationDialog::execute" );
	UnoDialog::execute();

	if ( maSaveAsURL.getLength() && mxCheckBox.is() )
	{
        sal_Bool bOpenNewDocument = static_cast< sal_Bool >( mxCheckBox->getState() );
        mrbOpenNewDocument = bOpenNewDocument;
	}

	endExecute( sal_True );
	return mbStatus;
}
