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



#include <xalanc/PlatformSupport/DOMStringHelper.hpp>
#include <xalanc/PlatformSupport/XalanMessageLoader.hpp>
#include <xalanc/PlatformSupport/StringTokenizer.hpp>
#include <xalanc/PlatformSupport/XalanUnicode.hpp>



#include <xalanc/DOMSupport/DOMServices.hpp>



#include "AVTPartSimple.hpp"
#include "AVTPartXPath.hpp"
#include "StylesheetConstructionContext.hpp"


namespace XALAN_CPP_NAMESPACE {



static const XalanDOMChar   theTokenDelimiterCharacters[] =
{
        XalanUnicode::charLeftCurlyBracket,
        XalanUnicode::charRightCurlyBracket,
        XalanUnicode::charApostrophe,
        XalanUnicode::charQuoteMark,
        0
};



static const XalanDOMChar   theLeftCurlyBracketString[] =
{
        XalanUnicode::charLeftCurlyBracket,
        0
};



static const XalanDOMChar   theRightCurlyBracketString[] =
{
        XalanUnicode::charRightCurlyBracket,
        0
};



const XalanDOMString    AVT::s_emptyString(XalanMemMgrs::getDummyMemMgr());



typedef XPathConstructionContext::GetCachedString   GetCachedString;



/**
 * Construct an AVT by parsing the string, and either 
 * constructing a vector of AVTParts, or simply hold 
 * on to the string if the AVT is simple.
 */
AVT::AVT(
            StylesheetConstructionContext&  constructionContext,
            const Locator*                  locator,
            const XalanDOMChar*             name,
            const XalanDOMChar*             stringedValue,
            const PrefixResolver&           resolver) :
        m_parts(0),
        m_partsSize(0),
        m_simpleString(0),
        m_simpleStringLength(0),
        m_name(constructionContext.getPooledString(name))
{
    StringTokenizer     tokenizer(stringedValue, theTokenDelimiterCharacters, true);

    const StringTokenizer::size_type    nTokens = tokenizer.countTokens();

    if(nTokens < 2)
    {
        // Do the simple thing
        m_simpleStringLength = length(stringedValue);

        m_simpleString = constructionContext.allocateXalanDOMCharVector(stringedValue, m_simpleStringLength, false);
    }
    else
    {
        // This over-allocates, but we probably won't waste that much space.  If necessary,
        // we could tokenize twice, just counting the numbers of AVTPart instances we
        // will need the first time.
        m_parts = constructionContext.allocateAVTPartPointerVector(nTokens + 1);

        XalanDOMString  buffer(constructionContext.getMemoryManager());
        XalanDOMString  exprBuffer(constructionContext.getMemoryManager());
        XalanDOMString  t(constructionContext.getMemoryManager()); // base token
        XalanDOMString  lookahead(constructionContext.getMemoryManager()); // next token

        while (tokenizer.hasMoreTokens())
        {
            if (lookahead.empty() == false)
            {
                t = lookahead;

                lookahead.clear();
            }
            else
            {
                nextToken(constructionContext, locator, tokenizer, t);
            }

            if (t.length() == 1)
            {
                const XalanDOMChar  theChar = t[0];

                switch(theChar)
                {
                    case(XalanUnicode::charLeftCurlyBracket):
                    {
                        // Attribute Value Template start
                        nextToken(constructionContext, locator, tokenizer, lookahead);

                        if(equals(lookahead, theLeftCurlyBracketString))
                        {
                            // Double braces mean escape to show brace
                            buffer.append(lookahead);

                            lookahead.clear();

                            break; // from switch
                        }
                        else
                        {
                            if(buffer.empty() == false)
                            {
                                assert(m_partsSize + 1 < nTokens);

                                m_parts[m_partsSize++] =
                                    constructionContext.createAVTPart(
                                        buffer.c_str(),
                                        buffer.length());

                                buffer.clear();
                            }
                                    
                            exprBuffer.clear();

                            while (lookahead.empty() == false && !equals(lookahead, theRightCurlyBracketString))
                            {
                                if (lookahead.length() == 1)
                                {
                                    switch(lookahead[0])
                                    {
                                        case XalanUnicode::charApostrophe:
                                        case XalanUnicode::charQuoteMark:
                                        {
                                            // String start
                                            exprBuffer.append(lookahead);

                                            const XalanDOMChar  quote[2] =
                                            {
                                                lookahead[0],
                                                0
                                            };

                                            // Consume stuff 'till next quote
                                            nextToken(constructionContext, locator, tokenizer, lookahead);

                                            while(!equals(lookahead, quote))
                                            {
                                                exprBuffer.append(lookahead);

                                                nextToken(constructionContext, locator, tokenizer, lookahead);
                                            }

                                            exprBuffer.append(lookahead);

                                            break;
                                        }

                                        case XalanUnicode::charLeftCurlyBracket:
                                            {
                                                GetCachedString     theGuard(constructionContext);

                                                // What's another brace doing here?
                                                constructionContext.problem(
                                                    StylesheetConstructionContext::eXSLTProcessor,
                                                    StylesheetConstructionContext::eError,
                                                    XalanMessageLoader::getMessage(
                                                        theGuard.get(),
                                                        XalanMessages::LeftBraceCannotAppearWithinExpression),
                                                    locator,
                                                    0);
                                                break;
                                            }

                                        default:
                                            // part of the template stuff, just add it.
                                            exprBuffer.append(lookahead);
                                            break;

                                    } // end inner switch
                                } // end if lookahead length == 1
                                else
                                {
                                    // part of the template stuff, just add it.
                                    exprBuffer.append(lookahead);
                                }

                                nextToken(constructionContext, locator, tokenizer, lookahead);
                            } // end while(!equals(lookahead, "}"))
                            assert(equals(lookahead, theRightCurlyBracketString));

                            // Proper close of attribute template. Evaluate the
                            // expression.
                            buffer.clear();

                            assert(m_partsSize + 1 < nTokens);

                            m_parts[m_partsSize++] =
                                constructionContext.createAVTPart(
                                    locator,
                                    exprBuffer.c_str(),
                                    exprBuffer.length(),
                                    resolver);

                            lookahead.clear(); // breaks out of inner while loop
                        }
                        break;
                    }
                    case(XalanUnicode::charRightCurlyBracket):
                    {
                        nextToken(constructionContext, locator, tokenizer, lookahead);

                        if (equals(lookahead, theRightCurlyBracketString))
                        {
                            // Double brace mean escape to show brace
                            buffer.append(lookahead);

                            lookahead.clear(); // swallow
                        }
                        else
                        {
                            GetCachedString     theGuard(constructionContext);

                            constructionContext.problem(
                                StylesheetConstructionContext::eXSLTProcessor,
                                StylesheetConstructionContext::eError,
                                XalanMessageLoader::getMessage(
                                    theGuard.get(),
                                    XalanMessages::UnmatchedWasFound),
                                locator,
                                0);

                        }
                        break;
                    }
                    default:
                    {
                        // Anything else just add to string.
                        buffer.append(1, theChar);
                    }
                } // end switch t
            } // end if length == 1
            else
            {
                // Anything else just add to string.
                buffer.append(t);
            }
        } // end while(tokenizer.hasMoreTokens())

        if (buffer.empty() == false)
        {
            assert(m_partsSize + 1 < nTokens);

            m_parts[m_partsSize++] =
                constructionContext.createAVTPart(
                    buffer.c_str(),
                    buffer.length());

            buffer.clear();
        }
    } // end else nTokens > 1
}



AVT::~AVT()
{
}



void
AVT::doEvaluate(
            XalanDOMString&         buf,
            XalanNode*              contextNode,
            const PrefixResolver&   prefixResolver,
            XPathExecutionContext&  executionContext) const
{
    if(m_partsSize != 0)
    {
        for(size_type i = 0; i < m_partsSize; i++)
        {
            assert(m_parts[i] != 0);

            m_parts[i]->evaluate(buf, contextNode, prefixResolver, executionContext);
        }
    }
}



void
AVT::doEvaluate(
            XalanDOMString&         buf,
            const PrefixResolver&   prefixResolver,
            XPathExecutionContext&  executionContext) const
{
    if(m_partsSize != 0)
    {
        for(size_type i = 0; i < m_partsSize; i++)
        {
            assert(m_parts[i] != 0);

            m_parts[i]->evaluate(buf, prefixResolver, executionContext);
        }
    }
}



void
AVT::nextToken(
            StylesheetConstructionContext&  constructionContext,
            const Locator*                  locator,
            StringTokenizer&                tokenizer,
            XalanDOMString&                 token)
{
    if (tokenizer.hasMoreTokens() == false)
    {
        GetCachedString     theGuard(constructionContext);

        constructionContext.problem(
            StylesheetConstructionContext::eXSLTProcessor,
            StylesheetConstructionContext::eError,
            XalanMessageLoader::getMessage(
                theGuard.get(),
                XalanMessages::AttributeValueTemplateHasMissing),
            locator,
            0);
    }
    else
    {
        tokenizer.nextToken(token);
    }
}



}
