/**************************************************************
 *
 * 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 <vcl/svapp.hxx>

// This works and was used before for standalone test, not sure why
// we'd want it.
#define LAYOUT_WEAK 1
#include "uno.hxx"

#include <cstdio>
#include <cstdlib>
#include <sys/stat.h>

#include <com/sun/star/xml/sax/SAXException.hpp>
#include <comphelper/processfactory.hxx>
#include <cppuhelper/bootstrap.hxx>
#include <rtl/ustring.hxx>
#include <ucbhelper/configurationkeys.hxx>
#include <ucbhelper/contentbroker.hxx>

#define SORT_DLG 1 /* requires sfx2, svx to be compiled */
#if SORT_DLG
#include "scitems.hxx"
#include "uiitems.hxx"
#endif /* SORT_DLG */

#include "editor.hxx"

#include "plugin.hxx"
#undef _LAYOUT_POST_HXX

#include "recover.hxx"
#undef _LAYOUT_POST_HXX

#if SORT_DLG
#include "sortdlg.hxx"
#undef _LAYOUT_POST_HXX
#endif /* SORT_DLG */

#include "wordcountdialog.hxx"
#undef _LAYOUT_POST_HXX

#include "zoom.hxx"
#undef _LAYOUT_POST_HXX

#include <layout/layout-pre.hxx>

using namespace ::rtl;
using namespace ::cppu;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;

class LayoutTest : public Application
{
    Reference< XComponentContext > mxContext;
    Reference< lang::XMultiServiceFactory > mxMSF;
    OUString mInstallDir;
    OUString mTestDialog;
    bool mEditMode;
    std::list< OUString > mFiles;

public:
    LayoutTest( char const* installDir );

    void RunEditor();
    void RunFiles();
    void ExceptionalMain();
    void Init();
    void InitUCB();
    void LoadFile( OUString const &aName );
    void Main();
    void ParseCommandLine();
};

static void usage()
{
    fprintf (stderr, "usage: test [--inst OOO_INSTALL_PREFIX] [DIALOG.XML]... | --test [DIALOG.XML]\n" );
    exit( 2 );
}

static uno::Reference< lang::XSingleServiceFactory > get_factory( char const *service )
{
    uno::Reference< lang::XSingleServiceFactory > xFactory(
        comphelper::createProcessComponent(
            rtl::OUString::createFromAscii( service ) ), uno::UNO_QUERY );

    if ( !xFactory.is() )
        fprintf( stderr, "error loading: %s\n", service );
    return xFactory;
}

#define GET_FACTORY(x) get_factory( #x )

void LayoutTest::LoadFile( const OUString &aTestFile )
{
    fprintf( stderr, "TEST: layout instance\n" );

    uno::Reference< lang::XSingleServiceFactory > xFactory
        = GET_FACTORY( com.sun.star.awt.Layout );
    if ( !xFactory.is() )
    {
        fprintf( stderr, "Layout engine not installed\n" );
        throw uno::RuntimeException(
            rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Layout engine not installed" ) ),
            uno::Reference< uno::XInterface >() );
    }
    fprintf( stderr, "TEST: initing root\n" );

    uno::Sequence< uno::Any > aParams( 1 );
    aParams[0] <<= aTestFile;

    uno::Reference< awt::XLayoutRoot > xRoot (
        xFactory->createInstanceWithArguments( aParams ),
        uno::UNO_QUERY );

    fprintf( stderr, "TEST: file loaded\n" );
}

void LayoutTest::InitUCB()
{
    OUString aEmpty;
    Sequence< Any > aArgs( 6 );
    aArgs[0]
        <<= OUString::createFromAscii( UCB_CONFIGURATION_KEY1_LOCAL );
    aArgs[1]
        <<= OUString::createFromAscii( UCB_CONFIGURATION_KEY2_OFFICE );
    aArgs[2] <<= OUString::createFromAscii( "PIPE" );
    aArgs[3] <<= aEmpty;
    aArgs[4] <<= OUString::createFromAscii( "PORTAL" );
    aArgs[5] <<= aEmpty;

    if ( !::ucbhelper::ContentBroker::initialize( mxMSF, aArgs ) )
    {
        fprintf( stderr, "Failed to init content broker\n" );
        fprintf( stderr, "arg[0]: %s\n", UCB_CONFIGURATION_KEY1_LOCAL );
        fprintf( stderr, "arg[1]: %s\n", UCB_CONFIGURATION_KEY2_OFFICE );
    }
}

static void support_upstream_brand_prefix ()
{
    if ( char const* inst = getenv( "OOO_INSTALL_PREFIX" ) )
    {
        char const *brand_prefix = "/openoffice.org3";
        OUString brand_dir = OUString::createFromAscii( inst )
            + OUString::createFromAscii( brand_prefix );
        struct stat stat_info;
        if ( !stat ( OUSTRING_CSTR( brand_dir ), &stat_info ) )
        {
            OSL_TRACE( "Appending %s to OOO_INSTALL_PREFIX", brand_prefix );
            setenv( "OOO_INSTALL_PREFIX", OUSTRING_CSTR( brand_dir ), 1 );
        }
    }
}

void LayoutTest::Init()
{
    ParseCommandLine();
    setenv( "OOO_INSTALL_PREFIX", OUSTRING_CSTR( mInstallDir ), 0 );
    support_upstream_brand_prefix ();
    OSL_TRACE( "OOO_INSTALL_PREFIX=%s", getenv( "OOO_INSTALL_PREFIX" ) );

    mxContext = defaultBootstrap_InitialComponentContext();
    mxMSF = new UnoBootstrapLayout( Reference< lang::XMultiServiceFactory >( mxContext->getServiceManager(), UNO_QUERY ) );
    ::comphelper::setProcessServiceFactory( mxMSF );
    InitUCB();
}

void LayoutTest::ParseCommandLine()
{
    printf ("%s\n", __PRETTY_FUNCTION__);
    for ( sal_uInt16 i = 0; i < GetCommandLineParamCount(); i++ )
    {
        OUString aParam = OUString( GetCommandLineParam( i ) );
        if ( aParam.equalsAscii( "-h" ) || aParam.equalsAscii( "--help" ) )
            usage();
        if ( aParam.equalsAscii( "--inst" ) )
        {
            if ( i >= GetCommandLineParamCount() - 1)
                usage();
            mInstallDir = GetCommandLineParam( ++i );
            setenv( "OOO_INSTALL_PREFIX", OUSTRING_CSTR( mInstallDir ), 1 );
        }
        else if ( aParam.equalsAscii( "--test" ) )
        {
            mTestDialog = OUString::createFromAscii( "zoom" );
            if (i + 1 < GetCommandLineParamCount())
                mTestDialog = GetCommandLineParam( ++i );
        }
        else if ( aParam.equalsAscii( "--editor" ) )
            mEditMode = true;
        else
            mFiles.push_back( aParam );
    }

    if ( mFiles.size() <= 0 )
        mFiles.push_back( OUString::createFromAscii( "layout.xml" ) );
}

void LayoutTest::RunEditor()
{
    OUString aFile;
    if ( !mFiles.empty()
        && mFiles.front().compareToAscii( "layout.xml" ) != 0 )
        aFile = mFiles.front();
    Editor editor( mxMSF, aFile );
    editor.Show();
    editor.Execute();
}

short RunDialog( Dialog& dialog )
{
    dialog.Show();
    short result = dialog.Execute();
    fprintf( stderr, "Done: dialog execute exited:%d\n", result);
    return result;
}

#undef Dialog
short RunDialog( ::Dialog& dialog )
{
    dialog.Show();
    short result = dialog.Execute();
    fprintf( stderr, "Done: dialog execute exited:%d\n", result);
    return result;
}

#if SORT_DLG
static void LoadSC()
{
    get_factory( "com.sun.star.comp.sfx2.DocumentTemplates" );
    get_factory( "com.sun.star.comp.Calc.SpreadsheetDocument" );
    GET_FACTORY( com.sun.star.i18n.Transliteration.l10n );
}
#endif /* SORT_DLG */

void TestDialog( OUString const& name )
{
    if ( 0 )
        ;
    else if ( name.equalsAscii( "plugin" ) )
    {
        PluginDialog plugin ( 0 );
        RunDialog( plugin );
    }
    else if ( name.equalsAscii( "query" ) )
    {
        QueryBox query ( 0, "Do you want to do?", "do");
        RunDialog( query );
    }
    else if ( name.equalsAscii( "query-compat" ) )
    {
        QueryBox query ( 0,
                         WinBits( WB_YES_NO | WB_DEF_YES ),
//                         WinBits( WB_ABORT_RETRY_IGNORE ),
                         OUString::createFromAscii ("Do you want to do?"));
        RunDialog( query );
    }
    else if ( name.equalsAscii( "recover" ) )
    {
        SvxRecoverDialog recover ( 0 );
        RunDialog( recover );
    }
#if SORT_DLG
    else if ( name.equalsAscii( "sort" ) )
    {
        LoadSC();
        ScSortDlg sort (0, 0);
        RunDialog( sort );
    }
#endif /* SORT_DLG */
    else if ( name.equalsAscii( "wordcount" ) )
    {
        SwWordCountDialog words ( 0 );
        RunDialog( words );
    }
    else if ( name.equalsAscii( "zoom" ) )
    {
        SvxZoomDialog zoom( 0 );
        RunDialog( zoom );
    }
}

void LayoutTest::RunFiles()
{
    fprintf( stderr, "TEST: loading files\n" );
    for ( std::list< OUString >::iterator  i = mFiles.begin(); i != mFiles.end(); i++ )
        LoadFile( *i );
    fprintf( stderr, "TEST: executing\n" );
    Execute();
    fprintf( stderr, "TEST: done executing\n" );
}

void LayoutTest::ExceptionalMain()
{
    if ( mTestDialog.getLength() )
        TestDialog( mTestDialog );
    else if ( mEditMode )
        RunEditor();
    else
        RunFiles();
}

void LayoutTest::Main()
{
    try
    {
        ExceptionalMain();
    }
    catch (xml::sax::SAXException & rExc)
    {
        OString aStr( OUStringToOString( rExc.Message,
                                         RTL_TEXTENCODING_ASCII_US ) );
        uno::Exception exc;
        if (rExc.WrappedException >>= exc)
        {
            aStr += OString( " >>> " );
            aStr += OUStringToOString( exc.Message, RTL_TEXTENCODING_ASCII_US );
        }
        fprintf (stderr, "Parsing error: '%s'\n", aStr.getStr());
        OSL_ENSURE( 0, aStr.getStr() );
    }
    catch ( uno::Exception & rExc )
    {
        OString aStr( OUStringToOString( rExc.Message,
                                         RTL_TEXTENCODING_ASCII_US ) );
        fprintf (stderr, "UNO error: '%s'\n", aStr.getStr());
        OSL_ENSURE( 0, aStr.getStr() );
    }

    Reference< lang::XComponent > xComp( mxContext, UNO_QUERY );
    if ( xComp.is() )
        xComp->dispose();
}

LayoutTest::LayoutTest( char const* installDir )
    : mInstallDir( OUString::createFromAscii ( installDir ) )
{
}

LayoutTest layout_test( "/usr/local/lib/ooo" );