/*
 * 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 <xalanc/Include/PlatformDefinitions.hpp>



#include <cstdlib>
#include <cstring>
#include <iostream>



#if !defined(NDEBUG) && defined(_MSC_VER)
#include <crtdbg.h>
#endif



#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/util/OutOfMemoryException.hpp>



#include <xalanc/Include/XalanAutoPtr.hpp>
#include <xalanc/Include/XalanMemoryManagement.hpp>



#include <xalanc/PlatformSupport/XalanMessageLoader.hpp>



#include <xalanc/XalanTransformer/XalanTransformer.hpp>



#if defined(_MSC_VER)
#define XALAN_USE_WINDOWS_TIMING
#endif

#if defined(XALAN_USE_WINDOWS_TIMING)
#include "windows.h"
#else
#include <ctime>
using std::clock;
using std::clock_t;
#endif



using std::cerr;
using std::cin;
using std::cout;
using std::endl;
using std::ostream;

using std::atoi;
using std::strcmp;
using std::strlen;



void
Usage()
{
    using xalanc::XalanDOMString;
    using xalanc::XalanMessageLoader;
    using xalanc::XalanMessages;
    using xalanc::XalanMemMgrs;
    using xercesc::MemoryManager;

    MemoryManager&  theManager = XalanMemMgrs::getDefaultXercesMemMgr();

    bool    bErrorState = true; // means OK

    XalanDOMString  szXalanVersion(theManager);
    XalanMessageLoader::getMessage(
        szXalanVersion,
        XalanMessages::XalanExeHelpMenuXalanVersion_1Param,
        XALAN_FULLVERSIONDOT);

    XalanDOMString  szXercesVersion(theManager);
    XalanMessageLoader::getMessage(
        szXercesVersion,
        XalanMessages::XalanExeHelpMenuXercesVersion_1Param,
        XERCES_FULLVERSIONDOT);

    try
    {
        XalanDOMString::CharVectorType  cvtXalanVersion(theManager);
        szXalanVersion.transcode(cvtXalanVersion);

        XalanDOMString::CharVectorType  cvtXercesVersion(theManager);
        szXercesVersion.transcode(cvtXercesVersion);

        cerr << &cvtXalanVersion[0] << endl;
        cerr << &cvtXercesVersion[0] << endl;
    }
    catch(const XalanDOMString::TranscodingError&) 
    {
        cerr << endl
             << "Transcoding error: wrong XalanC or XercesC versions."
             << endl;

        bErrorState = false;
    } 

    XalanDOMString::CharVectorType  cvtXalanExeHelpMenu(theManager);

    XalanDOMString theBuffer(theManager);

    for (int i = XalanMessages::XalanExeHelpMenu;
            bErrorState && (i <=  XalanMessages::XalanExeHelpMenu12);
                ++i)
    {
        try
        {
            
            XalanMessageLoader::getMessage(
                theBuffer,
                XalanMessages::Codes(i));

            theBuffer.transcode(cvtXalanExeHelpMenu);

            cerr  << &cvtXalanExeHelpMenu[0] << endl;
        }
        catch(const XalanDOMString::TranscodingError&) 
        {
            cerr << endl
                 << "Cannot read help message "
                 << i
                 << "."
                 << endl;

            bErrorState = false;
        }
    }
}



using xalanc::XalanTransformer;
using xalanc::XSLTInputSource;
using xalanc::XSLTResultTarget;



class Params
{
public:

    Params(unsigned long    maxParams) :
        m_validate(false),
        m_useStylesheetPI(false),
        m_omitMETATag(false),
        m_noURLEscaping(false),
        m_showTiming(false),
        m_indentAmount(-1),
        m_inFileName(0),
        m_xslFileName(0),
        m_outFileName(0),
        m_encoding(0),
        m_params(),
        m_maxParams(maxParams),
        m_currentParam(0)
    {
    }

    bool
    addParam(
            const char*     name,
            const char*     expression)
    {
        if (m_currentParam == m_maxParams)
        {
            return false;
        }
        else
        {
            // Allocate memory if necessary...
            if (m_params.get() == 0)
            {
                m_params.reset(new ParamPair[m_maxParams]);
            }
            assert(m_params.get() != 0);

            m_params[m_currentParam].m_name = name;
            m_params[m_currentParam].m_expression = expression;

            ++m_currentParam;

            return true;
        }
    };

    void
    setParams(XalanTransformer&     theTransformer) const
    {
        theTransformer.setUseValidation(m_validate);

        if (m_omitMETATag == true)
        {
            theTransformer.setOmitMETATag(XalanTransformer::eOmitMETATagYes);
        }

        if (m_noURLEscaping == true)
        {
            theTransformer.setEscapeURLs(XalanTransformer::eEscapeURLsNo);
        }

        if (m_indentAmount >= 0)
        {
            theTransformer.setIndent(m_indentAmount);
        }

        for(unsigned long i = 0; i < m_currentParam; ++i)
        {
            theTransformer.setStylesheetParam(
                m_params[i].m_name,
                m_params[i].m_expression);
        }
    }

    bool            m_validate;
    bool            m_useStylesheetPI;
    bool            m_omitMETATag;
    bool            m_noURLEscaping;
    bool            m_showTiming;

    int             m_indentAmount;

    const char*     m_inFileName;
    const char*     m_xslFileName;
    const char*     m_outFileName;

    const char*     m_encoding;

    unsigned long
    getMaxParams() const
    {
        return m_maxParams;
    }

private:

    struct ParamPair
    {
        ParamPair() :
            m_name(0),
            m_expression(0)
        {
        }

        const char*     m_name;
        const char*     m_expression;
    };

    typedef xalanc::XalanArrayAutoPtr<ParamPair>  ArrayAutoPtrType;

    ArrayAutoPtrType        m_params;

    const unsigned long     m_maxParams;
    unsigned long           m_currentParam;
};



bool
getArgs(
            int         argc,
            char*       argv[],
            Params&     params)
{
    bool fSuccess = true;

    for (int i = 1; i < argc && fSuccess == true; ++i)
    {
        if (argv[i][0] == '-' && argv[i][1] != '\0')
        {
            if (argv[i][2] != '\0')
            {
                fSuccess = false;
            }
            else if (params.m_inFileName != 0 || params.m_xslFileName != 0)
            {
                fSuccess = false;
            }
            else if (argv[i][1] == 'a') 
            {
                params.m_useStylesheetPI = true;
            }
            else if (argv[i][1] == 'e') 
            {
                ++i;

                if(i < argc && argv[i][0] != '-' &&
                   strlen(argv[i]) != 0)
                {
                    params.m_encoding = argv[i];
                }
                else
                {
                    fSuccess = false;
                }
            }
            else if (argv[i][1] == 'i') 
            {
                ++i;

                if(i < argc && argv[i][0] != '-' &&
                   strlen(argv[i]) != 0)
                {
                    params.m_indentAmount = atoi(argv[i]);
                }
                else
                {
                    fSuccess = false;
                }
            }
            else if (argv[i][1] == 'm') 
            {
                params.m_omitMETATag = true;
            }
            else if (argv[i][1] == 'o') 
            {
                ++i;

                if(i < argc && argv[i][0] != '-' &&
                   strlen(argv[i]) != 0)
                {
                    params.m_outFileName = argv[i];
                }
                else
                {
                    fSuccess = false;
                }
            }
            else if (argv[i][1] == 'p') 
            {
                ++i;

                if(i >= argc || argv[i][0] == '-')
                {
                    fSuccess = false;
                }
                else
                {
                    const char* const   name = argv[i];

                    ++i;

                    // Don't check for '-' here, since that might
                    // be a valid character in a parameter value.
                    if(i >= argc)
                    {
                        fSuccess = false;
                    }
                    else
                    {
                        const char* const   value = argv[i];

                        if (params.addParam(name, value) == false)
                        {
                            cerr << "The maximum number of parameters is "
                                 << params.getMaxParams()
                                 << "."
                                 << endl;

                            fSuccess = false;
                        }
                    }
                }
            }
            else if (argv[i][1] == 't') 
            {
                params.m_showTiming = true;
            }
            else if (argv[i][1] == 'u') 
            {
                params.m_noURLEscaping = true;
            }
            else if (argv[i][1] == 'v')
            {
                params.m_validate = true;
            }
            else
            {
                fSuccess = false;
            }
        }
        else if (params.m_inFileName == 0 &&
                 strlen(argv[i]) != 0)
        {
            params.m_inFileName = argv[i];

            if (strlen(params.m_inFileName) == 0)
            {
                fSuccess = false;
            }
        }
        else if (params.m_xslFileName == 0 &&
                 strlen(argv[i]) != 0 &&
                 params.m_useStylesheetPI == false)
        {
            params.m_xslFileName = argv[i];

            if (strlen(params.m_xslFileName) == 0)
            {
                fSuccess = false;
            }
        }
        else
        {
            fSuccess = false;
        }
    }

    if (fSuccess == true && params.m_inFileName == 0)
    {
        return false;
    }
    else if (params.m_xslFileName == 0)
    {
        return params.m_useStylesheetPI;
    }
    else if (strcmp(params.m_xslFileName, params.m_inFileName) == 0)
    {
        return false;
    }
    else
    {
        return fSuccess;
    }
}



#if defined(XALAN_USE_WINDOWS_TIMING)
typedef LARGE_INTEGER   ClockType;
#else
typedef std::clock_t    ClockType;
#endif

typedef ostream         OstreamType;


inline ClockType
getClock()
{
#if defined(XALAN_USE_WINDOWS_TIMING)
    ClockType   theResult;

    QueryPerformanceCounter(&theResult);

    return theResult;
#else
    return std::clock();
#endif
}



#if defined(XALAN_USE_WINDOWS_TIMING)
inline ClockType
getPerformanceFrequencyInMilliseconds()
{
    ClockType   theInterval;

    QueryPerformanceFrequency(&theInterval);

    theInterval.QuadPart /= 1000UL;

    return theInterval;
}
#endif



void
writeElapsedMilliseconds(
            ClockType       theStartClock,
            ClockType       theEndClock,
            OstreamType&    theStream)
{
#if defined(XALAN_USE_WINDOWS_TIMING)
    static const ClockType  theInterval =
        getPerformanceFrequencyInMilliseconds();

    char        theBuffer[1000];

    ClockType     theDiff;
    
    theDiff.QuadPart =
        theEndClock.QuadPart - theStartClock.QuadPart;

    ClockType     theResult;
    ClockType     theRemainder;
    
    theResult.QuadPart =
        theDiff.QuadPart / theInterval.QuadPart;

    theRemainder.QuadPart =
        theDiff.QuadPart % theInterval.QuadPart;

    sprintf(
        theBuffer,
        "%I64d.%I64d",
        theResult.QuadPart,
        theRemainder.QuadPart);

    theStream << theBuffer;
#else
    theStream << (double(theEndClock - theStartClock) /
                        CLOCKS_PER_SEC) * 1000.0;
#endif
}



inline void
reportElapsedMilliseconds(
            const char*     theString,
            ClockType       theStartClock,
            ClockType       theEndClock,
            OstreamType&    theStream)
{
    theStream << theString;

    writeElapsedMilliseconds(
        theStartClock,
        theEndClock,
        theStream);

    theStream << " milliseconds.\n";
}



using xalanc::XalanParsedSource;
using xalanc::XalanCompiledStylesheet;


typedef XalanTransformer::EnsureDestroyParsedSource         SourceGuard;
typedef XalanTransformer::EnsureDestroyCompiledStylesheet   StylesheetGuard;



inline int
transform(
            XalanTransformer&           theTransformer,
            const Params&               theParams,
            const XSLTInputSource&      theSource,
            const XSLTResultTarget&     theTarget)
{
    if (theParams.m_showTiming == false)
    {
        return theTransformer.transform(
                    theSource,
                    theTarget);
    }
    else
    {
        ClockType   theStartClock = getClock();

        const XalanParsedSource*    theParsedSource = 0;

        int theResult = theTransformer.parseSource(theSource, theParsedSource);

        if (theResult == 0)
        {
            ClockType       theEndClock = getClock();

            reportElapsedMilliseconds(
                "Source tree parsing time: ",
                theStartClock,
                theEndClock,
                cerr);

            const SourceGuard   theGuard(theTransformer, theParsedSource);

            theStartClock = getClock();

            theResult = theTransformer.transform(*theParsedSource, theTarget);

            theEndClock = getClock();

            reportElapsedMilliseconds(
                "Transformation time, including stylesheet compilation: ",
                theStartClock,
                theEndClock,
                cerr);
        }

        return theResult;
    }
}



inline int
transform(
            XalanTransformer&           theTransformer,
            const Params&               theParams,
            const XSLTInputSource&      theSource,
            const XSLTInputSource&      theStylesheetSource,
            const XSLTResultTarget&     theTarget)
{
    if (theParams.m_showTiming == false)
    {
        return theTransformer.transform(
                theSource,
                theStylesheetSource,
                theTarget);
    }
    else
    {
        ClockType   theStartClock = getClock();

        const XalanParsedSource*    theParsedSource = 0;

        int     theResult =
            theTransformer.parseSource(
                                theSource,
                                theParsedSource);

        if (theResult == 0)
        {
            ClockType   theEndClock = getClock();

            reportElapsedMilliseconds(
                "Source tree parsing time: ",
                theStartClock,
                theEndClock,
                cerr);

            const SourceGuard   theGuard(theTransformer, theParsedSource);

            const XalanCompiledStylesheet*  theStylesheet = 0;

            theStartClock = getClock();

            theResult =
                theTransformer.compileStylesheet(
                    theStylesheetSource,
                    theStylesheet);

            if (theResult == 0)
            {
                theEndClock = getClock();

                reportElapsedMilliseconds(
                    "Stylesheet compilation time: ",
                    theStartClock,
                    theEndClock,
                    cerr);

                assert(theStylesheet != 0);

                const StylesheetGuard   theGuard(theTransformer, theStylesheet);

                theStartClock = getClock();

                theResult =
                    theTransformer.transform(
                        *theParsedSource,
                        theStylesheet,
                        theTarget);

                theEndClock = getClock();

                reportElapsedMilliseconds(
                    "Transformation time: ",
                    theStartClock,
                    theEndClock,
                    cerr);
            }
        }

        return theResult;
    }
}



inline int
transform(
            XalanTransformer&       theTransformer,
            const Params&           theParams,
            const XSLTInputSource&  theSource,
            const XSLTInputSource&  theStylesheetSource)
{
    using xalanc::XalanDOMString;
    using xalanc::XSLTResultTarget;
    using xercesc::MemoryManager;

    MemoryManager&  theManager = theTransformer.getMemoryManager();

    XSLTResultTarget    theTarget(theManager);

    if (theParams.m_encoding != 0)
    {
        const XalanDOMString    theEncoding(theParams.m_encoding, theManager);

        theTarget.setEncoding(theEncoding);
    }

    if (theParams.m_outFileName != 0)
    {
        theTarget.setFileName(theParams.m_outFileName);
    }
    else
    {
        theTarget.setByteStream(&cout);
    }

    if (theParams.m_useStylesheetPI == true)
    {
        return transform(
                    theTransformer,
                    theParams,
                    theSource,
                    theTarget);
    }
    else
    {
        return transform(
                    theTransformer,
                    theParams,
                    theSource,
                    theStylesheetSource,
                    theTarget);
    }
}



inline int
transform(
            XalanTransformer&       theTransformer,
            const Params&           theParams,
            const XSLTInputSource&  theSource)
{
    assert(
        theParams.m_useStylesheetPI == true ||
        theParams.m_xslFileName != 0);

    if (theParams.m_useStylesheetPI == true ||
        (theParams.m_xslFileName[0] == '-' &&
         theParams.m_xslFileName[1] == '\0'))
    {
        return transform(
                theTransformer,
                theParams,
                theSource,
                &cin);
    }
    else
    {
        return transform(
                theTransformer,
                theParams,
                theSource,
                XSLTInputSource(theParams.m_xslFileName));
    }
}



inline int
transform(
            XalanTransformer&   theTransformer,
            const Params&       theParams)
{
    assert(theParams.m_inFileName != 0);

    if (theParams.m_inFileName[0] == '-' &&
        theParams.m_inFileName[1] == '\0')
    {
        return transform(
                    theTransformer,
                    theParams,
                    &cin);
    }
    else
    {
        return transform(
                    theTransformer,
                    theParams,
                    theParams.m_inFileName);
    }
}



#if defined(XALAN_WINDOWS)

using xercesc::MemoryManager;

class WindowsMemoryManager : public xalanc::XalanMemoryManager
{
public:

    typedef xalanc::XalanSize_t   XalanSize_t;

    WindowsMemoryManager() :
        XalanMemoryManager(),
        m_handle(HeapCreate(HEAP_NO_SERIALIZE, 0, 0))
    {
        assert(m_handle != 0);
    }

    virtual
    ~WindowsMemoryManager()
    {
        HeapDestroy(m_handle);
    }

    /**
      * This method allocates requested memory.
      *
      * size The requested memory size
      *
      * Returns a pointer to the allocated memory
      */
    virtual void*
    allocate(size_type  size)
    {
        void* const     value =
                HeapAlloc(m_handle, HEAP_NO_SERIALIZE, size);

        if (value == 0)
        {
            throw xercesc::OutOfMemoryException();
        }

        return value;
    }

    /**
      * This method deallocates memory
      *
      */
    virtual void
    deallocate(void*    pointer)
    {
        HeapFree(m_handle, HEAP_NO_SERIALIZE, pointer);
    }

    MemoryManager*
    getExceptionMemoryManager()
    {
        return this;
    }

protected:

private:

    // These are not implemented.
    WindowsMemoryManager(const WindowsMemoryManager&);

    WindowsMemoryManager&
    operator=(const WindowsMemoryManager&);


    // Data members.
    const HANDLE    m_handle;
};
#endif



int
xsltMain(
            int     argc,
            char*   argv[])

{
    int theResult = -1;

    using xercesc::XMLPlatformUtils;

#if defined(XALAN_WINDOWS) && defined(NDEBUG)
    WindowsMemoryManager  theMemoryManager;

    // Call the static initializer for Xerces...
    XMLPlatformUtils::Initialize(
        xercesc::XMLUni::fgXercescDefaultLocale,
        0,
        0,
        &theMemoryManager);
#else
    // Call the static initializer for Xerces...
    XMLPlatformUtils::Initialize();

    using xercesc::MemoryManager;
 
    MemoryManager&  theMemoryManager =
            *XMLPlatformUtils::fgMemoryManager;
#endif

    // Initialize Xalan...
    XalanTransformer::initialize(theMemoryManager);

    {
        // we need to read the params after the XMLPlatformUtils::Initialize(),
        // because we may need the local and the local dlls for usage of the
        // Usage function.

        // Set the maximum number of params as half of argc - 1.
        // It's actually argc - 2, but that could get us into negative
        // numbers, so don't bother.  Also, always add 1, in case
        // (argc - 1) / 2 is 0.
        Params  theParams((argc - 1) / 2 + 1);

        if (getArgs(argc, argv, theParams) == false)
        {
            Usage();
        }
        else
        {
            // Create a XalanTransformer instance...
            XalanTransformer    theTransformer(theMemoryManager);

            // Set any options...
            theParams.setParams(theTransformer);

            theResult = transform(theTransformer, theParams);

            if (theResult != 0)
            {
                cerr << theTransformer.getLastError() << endl;
            }
        }
    }

    // Terminate Xalan...
    XalanTransformer::terminate();

    // Terminate Xerces...
    XMLPlatformUtils::Terminate();

    // Clean up the ICU, if it's integrated...
    XalanTransformer::ICUCleanUp();

    return theResult;
}



int
main(
            int     argc,
            char*   argv[])
 {
#if defined(_DEBUG) && defined(_MSC_VER)
    _CrtSetDbgFlag(
        _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);

    _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
    _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
#endif

    return xsltMain(argc, argv);
}
