/*
 * 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 "TraceListenerDefault.hpp"



#include <xalanc/PlatformSupport/PrintWriter.hpp>
#include <xalanc/PlatformSupport/XalanLocator.hpp>
#include <xalanc/PlatformSupport/XalanMessageLoader.hpp>



#include <xalanc/DOMSupport/DOMServices.hpp>



#include <xalanc/XPath/NodeRefListBase.hpp>
#include <xalanc/XPath/XPath.hpp>
#include <xalanc/XPath/XPathExecutionContext.hpp>



#include "Constants.hpp"
#include "ElemTextLiteral.hpp"
#include "ElemTemplate.hpp"
#include "GenerateEvent.hpp"
#include "SelectionEvent.hpp"
#include "StylesheetConstructionContext.hpp"
#include "StylesheetRoot.hpp"
#include "TracerEvent.hpp"



namespace XALAN_CPP_NAMESPACE {



TraceListenerDefault::TraceListenerDefault(
            PrintWriter&            thePrintWriter,
            MemoryManager&          theManager,
            bool                    traceTemplates,
            bool                    traceElements,
            bool                    traceGeneration,
            bool                    traceSelection) :
    TraceListener(),
    m_executionContext(0),
    m_printWriter(thePrintWriter),
    m_traceTemplates(traceTemplates),
    m_traceElements(traceElements),
    m_traceGeneration(traceGeneration),
    m_traceSelection(traceSelection),
    m_memoryManager(theManager)
{
}



TraceListenerDefault::TraceListenerDefault(
            XPathExecutionContext&  theExecutionContext,
            PrintWriter&            thePrintWriter,
            MemoryManager&          theManager,
            bool                    traceTemplates,
            bool                    traceElements,
            bool                    traceGeneration,
            bool                    traceSelection) :
    TraceListener(),
    m_executionContext(&theExecutionContext),
    m_printWriter(thePrintWriter),
    m_traceTemplates(traceTemplates),
    m_traceElements(traceElements),
    m_traceGeneration(traceGeneration),
    m_traceSelection(traceSelection),
    m_memoryManager(theManager)
{
}



TraceListenerDefault::~TraceListenerDefault()
{
}



void
TraceListenerDefault::trace(const TracerEvent&  ev)
{
    switch (ev.m_styleNode.getXSLToken())
    {
    case StylesheetConstructionContext::ELEMNAME_TEXT_LITERAL_RESULT:
        if (m_traceElements == true)
        {
            printNodeInfo(ev.m_styleNode);

            m_printWriter.print(": ");
            m_printWriter.print(ev.m_styleNode.getElementName());
            m_printWriter.print("    ");

            const ElemTextLiteral&  etl =
                static_cast<const ElemTextLiteral&>(ev.m_styleNode);

            m_printWriter.println(etl.getText());
        }
        break;

    case StylesheetConstructionContext::ELEMNAME_TEMPLATE:
        if (m_traceTemplates == true || m_traceElements == true)
        {
            const ElemTemplate&     et =
                static_cast<const ElemTemplate&>(ev.m_styleNode);

            XalanDOMString lineNumbString(m_memoryManager);

            NumberToDOMString(ev.m_styleNode.getLineNumber(), lineNumbString);

            XalanDOMString colNumbString(m_memoryManager);

            NumberToDOMString(ev.m_styleNode.getColumnNumber(), colNumbString);

            XalanDOMString  msg(m_memoryManager);

            m_printWriter.print(
                XalanMessageLoader::getMessage(
                    msg,
                    XalanMessages::LineNumberColumnNumber_2Params,
                    lineNumbString,
                    colNumbString));

            m_printWriter.print(": ");
            m_printWriter.print(ev.m_styleNode.getElementName());

            const XPath* const  theMatchPattern =
                et.getMatchPattern();

            if (0 != theMatchPattern)
            {
                m_printWriter.print(
                    XalanMessageLoader::getMessage(
                        msg,
                        XalanMessages::MatchIs_1Param,
                        theMatchPattern->getExpression().getCurrentPattern()));

            }

            const XalanQName&   theName = et.getNameAttribute();

            if (theName.isEmpty() == false)
            {
                m_printWriter.print(
                    XalanMessageLoader::getMessage(
                        msg,
                        XalanMessages::NameIs_1Param));

                const XalanDOMString&   theNamespace =
                    theName.getNamespace();

                if (theNamespace.empty() == false)
                {
                    m_printWriter.print(theNamespace);
                    m_printWriter.print(":");
                }

                m_printWriter.print(theName.getLocalPart());
                m_printWriter.print("\" ");
            }

            m_printWriter.println();
        }
        break;

    default:
        if (m_traceElements == true)
        {
            XalanDOMString lineNumbString(m_memoryManager);
            NumberToDOMString(ev.m_styleNode.getLineNumber(), lineNumbString);
            
            XalanDOMString colNumbString(m_memoryManager);
            NumberToDOMString(ev.m_styleNode.getColumnNumber(), colNumbString);

            XalanDOMString  msg(m_memoryManager);

            m_printWriter.print(
                XalanMessageLoader::getMessage(
                    msg,
                    XalanMessages::LineNumberColumnNumber_2Params,
                    lineNumbString,
                    colNumbString));

            m_printWriter.print(": ");
            m_printWriter.println(ev.m_styleNode.getElementName());
        }
        break;
    }
}



void
TraceListenerDefault::processNodeList(const NodeRefListBase&        nl)
{
    m_printWriter.println();

    const NodeRefListBase::size_type    n = nl.getLength();

    XalanDOMString  msg(m_memoryManager);

    if(n == 0)
    {
        m_printWriter.println(
            XalanMessageLoader::getMessage(
                msg,
                XalanMessages::EmptyNodeList));
    }
    else
    {
        for (NodeRefListBase::size_type i = 0; i < n; i++)
        {
            assert(nl.item(i) != 0);

            m_printWriter.print("     ");

            if (m_executionContext != 0)
            {
                DOMServices::getNodeData(*nl.item(i), *m_executionContext, msg);
            }
            else
            {
                DOMServices::getNodeData(*nl.item(i), msg);
            }

            m_printWriter.println(msg);
        }
    }
}



void
TraceListenerDefault::selected(const SelectionEvent&    ev)
{
    if (m_traceSelection == true)
    {
        const ElemTemplateElement&  ete = ev.m_styleNode;

        if (ev.m_styleNode.getLineNumber() == XalanLocator::getUnknownValue())
        {
            // You may not have line numbers if the selection is occuring from a
            // default template.

            ElemTemplateElement* const  parent = ete.getParentNodeElem();

            XalanDOMString  msg(m_memoryManager);

            if (parent == ete.getStylesheet().getStylesheetRoot().getDefaultRootRule())
            {
                m_printWriter.print(
                    XalanMessageLoader::getMessage(
                        msg,
                        XalanMessages::DefaultRootRule));
            }
            else if (parent == ete.getStylesheet().getStylesheetRoot().getDefaultTextRule())
            {
                m_printWriter.print(
                    XalanMessageLoader::getMessage(
                        msg,
                        XalanMessages::DefaultRootRule_1Param,
                        Constants::ATTRNAME_DATATYPE));
            }
            else if (parent == ete.getStylesheet().getStylesheetRoot().getDefaultRule())
            {
                m_printWriter.print(
                    XalanMessageLoader::getMessage(
                        msg,
                        XalanMessages::DefaultRootRule_1Param,
                        " "));
            }
        }
        else
        {
            XalanDOMString  msg(m_memoryManager);
            XalanDOMString  lineNumb(m_memoryManager);
            XalanDOMString  columnNumber(m_memoryManager);

            NumberToDOMString(ev.m_styleNode.getLineNumber(), lineNumb);

            NumberToDOMString( ev.m_styleNode.getColumnNumber(), columnNumber);

            m_printWriter.print(
                XalanMessageLoader::getMessage(
                    msg, 
                    XalanMessages::TextAndColumnNumber_2Param,
                    lineNumb,
                    columnNumber));
        }

        m_printWriter.print(ete.getElementName());
        m_printWriter.print(", ");
        m_printWriter.print(ev.m_attributeName);
        m_printWriter.print("=\"");
        m_printWriter.print(ev.m_xpathExpression);
        m_printWriter.print("\": ");

        if (ev.m_selection.null() == true)
        {
            if (ev.m_type == SelectionEvent::eBoolean)
            {
                m_printWriter.println(ev.m_boolean == true ? "true" : "false");
            }
            else if (ev.m_type == SelectionEvent::eNodeSet)
            {
                assert(ev.m_nodeList != 0);

                processNodeList(*ev.m_nodeList);
            }
        }
        else if(ev.m_selection->getType() == XObject::eTypeNodeSet)
        {
            const NodeRefListBase&  theNodeSet =
                m_executionContext != 0 ?
                    ev.m_selection->nodeset() :
                    ev.m_selection->nodeset();

            processNodeList(theNodeSet);
        }
        else
        {
            const XalanDOMString&   theString =
                m_executionContext != 0 ?
                    ev.m_selection->str(*m_executionContext) :
                    ev.m_selection->str();

            m_printWriter.println(theString);
        }
    }
}



void
TraceListenerDefault::generated(const GenerateEvent&    ev)
{
    if(m_traceGeneration == true)
    {
        switch(ev.m_eventType)
        {
        case GenerateEvent::EVENTTYPE_STARTDOCUMENT:
            m_printWriter.println("STARTDOCUMENT");
            break;

        case GenerateEvent::EVENTTYPE_ENDDOCUMENT:
            m_printWriter.println();
            m_printWriter.println("ENDDOCUMENT");
            break;

        case GenerateEvent::EVENTTYPE_STARTELEMENT:
            m_printWriter.print("STARTELEMENT: ");
            m_printWriter.println(ev.m_name);
            break;

        case GenerateEvent::EVENTTYPE_ENDELEMENT:
            m_printWriter.print("ENDELEMENT: ");
            m_printWriter.println(ev.m_name);
            break;

        case GenerateEvent::EVENTTYPE_CHARACTERS:
            m_printWriter.print("CHARACTERS: ");
            m_printWriter.println(ev.m_characters);
            break;

        case GenerateEvent::EVENTTYPE_CDATA:
            m_printWriter.print("CDATA: ");
            m_printWriter.println(ev.m_characters);
            break;

        case GenerateEvent::EVENTTYPE_COMMENT:
            m_printWriter.print("COMMENT: ");
            m_printWriter.println(ev.m_data);
            break;

        case GenerateEvent::EVENTTYPE_PI:
            m_printWriter.print("PI: ");
            m_printWriter.print(ev.m_name);
            m_printWriter.print(", ");
            m_printWriter.println(ev.m_data);
            break;

        case GenerateEvent::EVENTTYPE_ENTITYREF:
            m_printWriter.println("ENTITYREF: ");
            m_printWriter.println(ev.m_name);
            break;

        case GenerateEvent::EVENTTYPE_IGNORABLEWHITESPACE:
            m_printWriter.println("IGNORABLEWHITESPACE");
            break;
        }
    }
}



void
TraceListenerDefault::printNodeInfo(const ElemTemplateElement&  node)
{
    const XalanDOMString&   uri = node.getURI();

    XalanDOMString msg(m_memoryManager), lineNumb(m_memoryManager), columnNumb(m_memoryManager);

    NumberToDOMString(node.getLineNumber(), lineNumb);

    NumberToDOMString(node.getColumnNumber(), columnNumb);

    m_printWriter.print(
        XalanMessageLoader::getMessage(
            msg,
            XalanMessages::TextAndColumnNumber_2Param,
            lineNumb,
            columnNumb));

    if (uri.length() != 0)
    {
        m_printWriter.print(" (");
        m_printWriter.print(uri);
        m_printWriter.print(")");
    }
}



}
