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



#include <algorithm>



#include <xalanc/ICUBridge/ICUBridge.hpp>



#include <xalanc/Include/XalanAutoPtr.hpp>



#include <xalanc/PlatformSupport/DOMStringHelper.hpp>
#include <xalanc/PlatformSupport/XalanDecimalFormatSymbols.hpp>
#include <xalanc/PlatformSupport/XalanMessageLoader.hpp>



#include <xalanc/XPath/XPathExecutionContext.hpp>



namespace XALAN_CPP_NAMESPACE {



ICUFormatNumberFunctor::ICUFormatNumberFunctor(MemoryManager& theManager) :
    m_decimalFormatCache(theManager),
    m_defaultDecimalFormat(theManager, createDecimalFormat(theManager)),
    m_memoryManager(theManager)
{
}



ICUFormatNumberFunctor*
ICUFormatNumberFunctor::create(MemoryManager& theManager) 
{
    typedef ICUFormatNumberFunctor  ThisType;

    XalanAllocationGuard    theGuard(theManager, theManager.allocate(sizeof(ThisType)));

    ThisType* const     theResult =
        new (theGuard.get()) ThisType(theManager);

    theGuard.release();

    return theResult;
}



ICUFormatNumberFunctor::~ICUFormatNumberFunctor()
{
    using std::for_each;

    for_each(
        m_decimalFormatCache.begin(),
        m_decimalFormatCache.end(),
        DecimalFormatCacheStruct::DecimalFormatDeleteFunctor(m_memoryManager));
}



void
ICUFormatNumberFunctor::operator() (
        XPathExecutionContext&              executionContext,   
        double                              theNumber,
        const XalanDOMString&               thePattern,
        const XalanDecimalFormatSymbols*    theDFS,
        XalanDOMString&                     theResult,
        const XalanNode*                    context,
        const Locator*                      locator) const 
{
    if (!doFormat(theNumber, thePattern, theResult, theDFS))
    {
        const XPathExecutionContext::GetCachedString    theGuard(executionContext);

        executionContext.problem(
            XPathExecutionContext::eXSLTProcessor,
            XPathExecutionContext::eWarning,
            XalanMessageLoader::getMessage(
                theGuard.get(),
                XalanMessages::FormatNumberFailed),
            locator,
            context);
    }       
}



DecimalFormatType * 
ICUFormatNumberFunctor::getCachedDecimalFormat(const XalanDecimalFormatSymbols &theDFS) const
{
    using std::find_if;

    DecimalFormatCacheListType::iterator i =
        find_if(
            m_decimalFormatCache.begin(),
            m_decimalFormatCache.end(),
            DecimalFormatCacheStruct::DecimalFormatFindFunctor(&theDFS));

    if (i == m_decimalFormatCache.end())
    {
        return 0;
    }
    else
    {
        // Let's do a quick check to see if we found the first entry.
        // If so, we don't have to update the cache, so just return the
        // appropriate value...
        const DecimalFormatCacheListType::iterator  theBegin =
            m_decimalFormatCache.begin();

        if (i == theBegin)
        {
            return (*i).m_formatter;
        }
        else
        {
            // Save the formatter, because splice() may invalidate
            // the iterator.
            DecimalFormatType* const    theFormatter = (*i).m_formatter;

            // Move the entry to the beginning the cache
            m_decimalFormatCache.splice(theBegin, m_decimalFormatCache, i);

            return theFormatter;
        }
    }
}



bool
ICUFormatNumberFunctor::doFormat(   
        double                              theNumber,
        const XalanDOMString&               thePattern,
        XalanDOMString&                     theResult,
        const XalanDecimalFormatSymbols*    theDFS) const
{

    if (theDFS == 0)
    {
        return doICUFormat(theNumber, thePattern, theResult);
    }

    XalanDOMString  nonLocalPattern(m_memoryManager);

    UnlocalizePatternFunctor    formatter(*theDFS);

    formatter(thePattern, nonLocalPattern, m_memoryManager);


    DecimalFormatType* const    theFormatter =
        getCachedDecimalFormat(*theDFS);

    if (theFormatter != 0)
    {
        return doICUFormat(
                    theNumber,
                    nonLocalPattern,
                    theResult,
                    theFormatter);
    }
    else
    {
        DFAutoPtrType   theDecimalFormatGuard(
                            m_memoryManager,
                            createDecimalFormat(*theDFS, m_memoryManager));

        if (theDecimalFormatGuard.get() != 0)
        {
            // OK, there was no error, so cache the instance...
            cacheDecimalFormat(theDecimalFormatGuard.get(), *theDFS);

            // Release the collator, since it's in the cache and
            // will be controlled by the cache...
            DecimalFormatType* const    theDecimalFormat =
                theDecimalFormatGuard.releasePtr();

            return doICUFormat(
                        theNumber,
                        nonLocalPattern,
                        theResult,
                        theDecimalFormat);
        }
        else
        {
            return doICUFormat(theNumber,nonLocalPattern,theResult);
        }
    }
}



DecimalFormatType*
ICUFormatNumberFunctor::createDecimalFormat(
        const XalanDecimalFormatSymbols&    theXalanDFS,
        MemoryManager&                      theManager)
{
    UErrorCode theStatus = U_ZERO_ERROR;    

    // Use a XalanAutoPtr, to keep this safe until we construct the DecimalFormat instance.
    XalanAutoPtr<icu::DecimalFormatSymbols>  theDFS(new icu::DecimalFormatSymbols(theStatus));
    // We got a XalanDecimalFormatSymbols, so set the
    // corresponding data in the ICU DecimalFormatSymbols.
    theDFS->setSymbol(
        icu::DecimalFormatSymbols::kZeroDigitSymbol,
        UChar(theXalanDFS.getZeroDigit()));

    theDFS->setSymbol(
        icu::DecimalFormatSymbols::kGroupingSeparatorSymbol,
        UChar(theXalanDFS.getGroupingSeparator()));

    theDFS->setSymbol(
        icu::DecimalFormatSymbols::kDecimalSeparatorSymbol,
        UChar(theXalanDFS.getDecimalSeparator()));

    theDFS->setSymbol(
        icu::DecimalFormatSymbols::kPerMillSymbol,
        UChar(theXalanDFS.getPerMill()));

    theDFS->setSymbol(
        icu::DecimalFormatSymbols::kPercentSymbol,
        UChar(theXalanDFS.getPercent()));

    theDFS->setSymbol(
        icu::DecimalFormatSymbols::kDigitSymbol,
        UChar(theXalanDFS.getDigit()));

    theDFS->setSymbol(
        icu::DecimalFormatSymbols::kPatternSeparatorSymbol,
        UChar(theXalanDFS.getPatternSeparator()));

    theDFS->setSymbol(
        icu::DecimalFormatSymbols::kInfinitySymbol,
        ICUBridge::XalanDOMStringToUnicodeString(
            theManager,
            theXalanDFS.getInfinity()));

    theDFS->setSymbol(
        icu::DecimalFormatSymbols::kNaNSymbol,
        ICUBridge::XalanDOMStringToUnicodeString(
            theManager,
            theXalanDFS.getNaN()));

    theDFS->setSymbol(
        icu::DecimalFormatSymbols::kMinusSignSymbol,
        UChar(theXalanDFS.getMinusSign()));

    theDFS->setSymbol(
        icu::DecimalFormatSymbols::kCurrencySymbol,
        ICUBridge::XalanDOMStringToUnicodeString(
            theManager,
            theXalanDFS.getCurrencySymbol()));

    theDFS->setSymbol(
        icu::DecimalFormatSymbols::kIntlCurrencySymbol,
        ICUBridge::XalanDOMStringToUnicodeString(
            theManager,
            theXalanDFS.getInternationalCurrencySymbol()));

    theDFS->setSymbol(
        icu::DecimalFormatSymbols::kMonetarySeparatorSymbol,
        UChar(theXalanDFS.getMonetaryDecimalSeparator()));

    // Construct a DecimalFormat instance.
    DecimalFormatType*  theFormatter = 0;

    XalanConstruct(
        theManager,
        theFormatter,
        theStatus);

    // Guard this, just in case something happens before
    // we return it. 
    DFAutoPtrType   theGuard(theManager, theFormatter);

    if (U_SUCCESS(theStatus))
    {
        // Note that we release the XalanAutoPtr, since the
        // DecimalFormat will adopt the DecimalFormatSymbols instance.
        theGuard->adoptDecimalFormatSymbols(theDFS.release());

        return theGuard.releasePtr();
    } 
    else 
    {
        assert(false);

        return 0;
    }
}



void
ICUFormatNumberFunctor::cacheDecimalFormat(
    DecimalFormatType *                     theFormatter,
    const XalanDecimalFormatSymbols&        theDFS) const
{

    assert(theFormatter != 0);

    // Is the cache full?
    if (m_decimalFormatCache.size() == eCacheMax)
    {
        // Yes, so guard the collator instance, in case pop_back() throws...
        DFAutoPtrType   theDecimalFormatGuard(
                            m_memoryManager,
                            m_decimalFormatCache.back().m_formatter);

        m_decimalFormatCache.pop_back();
    }

    const DecimalFormatCacheListType::value_type    emptyDFC(m_memoryManager);

    m_decimalFormatCache.push_front(emptyDFC);

    DecimalFormatCacheListType::value_type&     theEntry = 
        m_decimalFormatCache.front();

    theEntry.m_formatter = theFormatter;
    theEntry.m_DFS = theDFS;
}



bool
ICUFormatNumberFunctor::doICUFormat(
        double                              theNumber,
        const XalanDOMString&               thePattern,
        XalanDOMString&                     theResult,
        DecimalFormatType*                  theFormatter) const
{
    UErrorCode theStatus = U_ZERO_ERROR;

    if (theFormatter == 0)
    {
        if (m_defaultDecimalFormat.get() != 0) 
        {
            theFormatter = m_defaultDecimalFormat.get();
        }
        else
        {
            return false;
        }
    }

    theFormatter->applyPattern(
        ICUBridge::XalanDOMStringToUnicodeString(m_memoryManager, thePattern),
        theStatus);

    if (U_SUCCESS(theStatus))
    {
        // Do the format...
        icu::UnicodeString   theUnicodeResult;
        theFormatter->format(theNumber, theUnicodeResult);
        ICUBridge::UnicodeStringToXalanDOMString(theUnicodeResult, theResult);
    }

    return U_SUCCESS(theStatus) ? true : false;
}

XalanDOMString&
ICUFormatNumberFunctor::UnlocalizePatternFunctor::operator()(
            const XalanDOMString&   thePattern,
            XalanDOMString&         theResult,
            MemoryManager&          theManager) const
{

    XalanDecimalFormatSymbols   defaultDFS(theManager);

    XalanDOMString::const_iterator iterator = thePattern.begin();

    while( iterator != thePattern.end())
    {
        
        if( m_DFS.getDecimalSeparator() == *iterator )
        {
            theResult.push_back(defaultDFS.getDecimalSeparator());
        }
        else if(m_DFS.getDigit() == *iterator)
        {
            theResult.push_back(defaultDFS.getDigit());
        }
        else if(m_DFS.getGroupingSeparator() == *iterator)
        {
            theResult.push_back(defaultDFS.getGroupingSeparator());
        }
        else if(m_DFS.getMinusSign() == *iterator)
        {
            theResult.push_back(defaultDFS.getMinusSign());
        }
        else if(m_DFS.getPatternSeparator() == *iterator)
        {
            theResult.push_back(defaultDFS.getPatternSeparator());
        }
        else if(m_DFS.getPercent() == *iterator)
        {
            theResult.push_back(defaultDFS.getPercent());
        }
        else if(m_DFS.getPerMill() == *iterator)
        {
            theResult.push_back(defaultDFS.getPerMill());
        }
        else if(m_DFS.getZeroDigit() == *iterator)
        {
            theResult.push_back(defaultDFS.getZeroDigit());
        }
        else
        {   
            switch(*iterator)
            {
            case XalanUnicode::charFullStop:
            case XalanUnicode::charNumberSign:
            case XalanUnicode::charComma:
            case XalanUnicode::charHyphenMinus:
            case XalanUnicode::charSemicolon:
            case XalanUnicode::charPercentSign:
            case XalanUnicode::charPerMilleSign:
            case XalanUnicode::charDigit_0:
                {
                    theResult.push_back(XalanUnicode::charAmpersand);
                    theResult.push_back(*iterator);
                    theResult.push_back(XalanUnicode::charAmpersand);
                }
            }
        }

        iterator++;
    }

    return theResult;
}

}
