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



#include "DOMStringHelper.hpp"
#include "XalanUnicode.hpp"



XALAN_CPP_NAMESPACE_BEGIN


#if defined(XALAN_INLINE_INITIALIZATION) && !defined(XALAN_INLINE_INITIALIZATION_IS_DEFINITION_BUG)
const int   XalanParsedURI::d_scheme;
const int   XalanParsedURI::d_authority;
const int   XalanParsedURI::d_query;
const int   XalanParsedURI::d_fragment;
#endif



/* Merge the components back into a complete URI string */
XalanDOMString& XalanParsedURI::make(XalanDOMString&        uri) const
{
    uri.erase();

    if (m_defined & d_scheme)
    {
        uri += m_scheme;
        uri += XalanUnicode::charColon;
    }
    if (m_defined & d_authority)
    {
        uri += XalanUnicode::charSolidus;
        uri += XalanUnicode::charSolidus;
        uri += m_authority;
    }
    uri += m_path;
    if (m_defined & d_query)
    {
        uri += XalanUnicode::charQuestionMark;
        uri += m_query;
    }
    if (m_defined & d_fragment)
    {
        uri += XalanUnicode::charNumberSign;
        uri += m_fragment;
    }
    return uri;
}

/* Parse a URI into component parts.
   Essentially implements the regex ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
 */
void XalanParsedURI::parse(
    const XalanDOMChar*         uriString,
    XalanDOMString::size_type   uriStringLen
)
{
    XalanDOMString::size_type index = 0;
    
    // Clear the components present mask
    m_defined = 0;

    // Scheme portion
    while (index < uriStringLen && 
                uriString[index] != XalanUnicode::charColon && 
                uriString[index] != XalanUnicode::charSolidus && 
                uriString[index] != XalanUnicode::charQuestionMark && 
                uriString[index] != XalanUnicode::charNumberSign)
    {
        ++index;
    }
    
    if (index > 0 && uriString[index] == XalanUnicode::charColon)
    {
        m_scheme = XalanDOMString(uriString, getMemoryManager(), index);
        ++index;
        m_defined |= d_scheme;
    }
    else
    {
        index = 0;
        m_scheme.clear();
    }

    // Authority portion
    if (index < uriStringLen - 1 &&
        uriString[index] == XalanUnicode::charSolidus && 
        uriString[index+1] == XalanUnicode::charSolidus) 
    {
        index += 2;
        XalanDOMString::size_type authority = index;

        while (index < uriStringLen &&
                uriString[index] != XalanUnicode::charSolidus && 
                uriString[index] != XalanUnicode::charQuestionMark && 
                uriString[index] != XalanUnicode::charNumberSign)
        {
            ++index;
        }
        if (index != authority)
        {
            m_authority = XalanDOMString(uriString + authority, getMemoryManager(), index - authority);
            m_defined |= d_authority;
        }
        else
            m_authority.clear();
    }
    else
    {
        m_authority.clear();
    }

    // Path portion
    XalanDOMString::size_type path = index;
    while (index < uriStringLen &&
            uriString[index] != XalanUnicode::charQuestionMark && 
            uriString[index] != XalanUnicode::charNumberSign)
    {
        ++index;
    }
    m_path = XalanDOMString(uriString + path,getMemoryManager(), index - path);

    // Query portion
    if (index < uriStringLen && uriString[index] == XalanUnicode::charQuestionMark)
    {
        ++index;
        XalanDOMString::size_type query = index;

        while (index < uriStringLen &&
                uriString[index] != XalanUnicode::charNumberSign)
        {
            ++index;
        }
        m_query = XalanDOMString(uriString + query,getMemoryManager(), index - query);
        m_defined |= d_query;
    }
    else
    {
        m_query.clear();
    }

    // Fragment portion
    if (index < uriStringLen && uriString[index] == XalanUnicode::charNumberSign)
    {
        ++index;
        m_fragment = XalanDOMString(uriString + index, getMemoryManager(), uriStringLen - index);
        m_defined |= d_fragment;
    }
    else
    {
        m_fragment.clear();
    }
}

/* Resolve this URI relative to another according to RFC2396, section 5.2 */
void XalanParsedURI::resolve(
    const XalanParsedURI &base
)
{
    if (base.isSchemeDefined() == false)
    {
        // Protect against a base URI that is relative...
        // This might become an assert or an exception.
    }
    // Handle references to the current document (step 2)
    else if ((m_defined & (d_scheme | d_authority | d_query)) == 0 &&
        m_path.empty())
    {
        m_defined = base.m_defined;
        if (base.m_defined & d_scheme)
            m_scheme    = base.m_scheme;
        if (base.m_defined & d_authority)
            m_authority = base.m_authority;

        m_path      = base.m_path;

        if (base.m_defined & d_query)
            m_query     = base.m_query;

        // There is an error/unclarity in the specification in step 2 in that
        // it doesn't state that the fragment should be inherited; however
        // it is clear from the examples that it should be
        if (!(m_defined & d_fragment))
        {
            m_fragment = base.m_fragment;
        }

        m_defined |= base.m_defined;
    }
    // A defined scheme component implies that this is an absolute URI (step 3)
    // Also allow a scheme without authority that matches the base scheme to be 
    // interpreted as a relative URI
    else if (!(m_defined & d_scheme) || ( 
            (base.m_defined & d_scheme) && !(m_defined & d_authority) 
            && equalsIgnoreCaseASCII(m_scheme, base.m_scheme)))
    {
        // Inherit the base scheme
        if (base.m_defined & d_scheme)
        {
            m_scheme = base.m_scheme;
            m_defined |= d_scheme;
        }

        // Step 4: If the authority is unm_defined then inherit it, otherwise skip to step 7
        if (!(m_defined & d_authority))
        {
            // Inherit the base authority
            if (base.m_defined & d_authority)
            {
                m_authority = base.m_authority;
                m_defined |= d_authority;
            }

            // Step 5: if the path starts with a / then it is absolute
            if (!(m_path.length() > 0 && m_path[0] == XalanUnicode::charSolidus))
            {
                // Step 6: merge relative path components

                // a) strip off characters after the right most slash in the base path
                XalanDOMString::size_type pathEnd = base.m_path.length();
                while (pathEnd > 0 && base.m_path[pathEnd - 1] != XalanUnicode::charSolidus)
                {
                    --pathEnd;
                }

                if (pathEnd > 0) 
                {
                    // b) append relative path
                    // This inserts the path portion from base...
                    m_path.insert(0, base.m_path, 0, pathEnd);
                }
                else
                {
                    // TODO, maybe raise an error here as this
                    // is a severely wonky looking URI
                }

                // c)->g remove various "./" and "../" segments
                for (XalanDOMString::size_type index = 0; index < m_path.length(); ) 
                {
                    // remove '<segment>/../' and ./
                    if (m_path[index] == XalanUnicode::charFullStop) 
                    {
                        if (index < m_path.length()-1 && 
                            m_path[index+1] == XalanUnicode::charSolidus) // ./
                        {
                            m_path.erase(index,2);
                            continue;
                        } 
                        else if (index == m_path.length()-1) // trailing /.
                        {
                            m_path.erase(index,1);
                            continue;
                        } 
                        // Note: also strips leading ../ in an attempt to get 
                        // something out of a bad m_path
                        else if (index < m_path.length()-2 && 
                                    m_path[index+1] == XalanUnicode::charFullStop && 
                                    m_path[index+2] == XalanUnicode::charSolidus) // ../
                        { 
                            const XalanDOMString::size_type     end = index + 2;
                            if (index > 0) --index;
                            for ( ; index > 0 && m_path[index-1] != XalanUnicode::charSolidus; index--) 
                                ;
                            if (index > 0) --index;
                            m_path.erase(index, end - index);
                            continue;
                        } 
                        else if (index == m_path.length()-2 && 
                                    m_path[index+1] == XalanUnicode::charFullStop) // trailing /..
                        {
                            const XalanDOMString::size_type     end = index + 2;
                            if (index > 0) --index;
                            for ( ; index > 0 && m_path[index-1] != XalanUnicode::charSolidus; index--) 
                                ;
                            m_path.erase(index, end - index);
                            continue;
                        }
                    }
                    for ( ; index < m_path.length() && m_path[index] != XalanUnicode::charSolidus ; ++index)
                    {
                    }
                    ++index;
                }
            }
        }
    }
}

/* Static helper function to perform a resolve without mucking about with this class */
XalanDOMString& XalanParsedURI::resolve(
    const XalanDOMChar          *relative,
    XalanDOMString::size_type   relativeLen,
    const XalanDOMChar          *base,
    XalanDOMString::size_type   baseLen,
    XalanDOMString&             theResult
)
{
    XalanParsedURI relativeURI(relative, relativeLen, theResult.getMemoryManager());
    XalanParsedURI baseURI(base, baseLen, theResult.getMemoryManager());

    relativeURI.resolve(baseURI);
    return relativeURI.make(theResult);
}

XALAN_CPP_NAMESPACE_END
