#ifndef __DCL_URI_H__
#define __DCL_URI_H__

#ifndef __DCL_EXCEPTION_H__
#include <dcl/core/Exception.h>
#endif
#ifndef __DCL_STRING_H__
#include <dcl/core/String.h>
#endif
#ifndef __DCL_COLLECTION_H__
#include <dcl/core/Collection.h>
#endif

__DCL_BEGIN_NAMESPACE

/*
    References
        http://www.faqs.org/rfcs/rfc2396.html
        RFC 2396 
            - Uniform Resource Identifiers (URI)
                : Generic Syntax
*/

class DCLNAPI URLEncoder
{
public:
    static String encode(const String& str);
};

class DCLNAPI URLDecoder
{
public:
    static String decode(const String& str);
};

class URISyntaxException;

class DCLNAPI URI : public Object
{
    DECLARE_CLASSINFO(URI)
public:
    URI(const char* pszURI)
        __DCL_THROWS1(URISyntaxException*);

    URI(const char* pszScheme,
        const char* pszSchemeSpecificPart,
        const char* pszFragment
        ) __DCL_THROWS1(URISyntaxException*);

    URI(const char* pszScheme,
        const char* pszUserInfo,
        const char* pszHost,
        int nPort,
        const char* pszPath,
        const char* pszQuery,
        const char* pszFragment
        ) __DCL_THROWS1(URISyntaxException*);

    URI(const char* pszScheme,
        const char* pszHost,
        const char* pszPath,
        const char* pszFragment
        ) __DCL_THROWS1(URISyntaxException*);

    URI(const char* pszScheme,
        const char* pszAuthority,
        const char* pszPath,
        const char* pszQuery,
        const char* pszFragment
        ) __DCL_THROWS1(URISyntaxException*);

    const String& scheme() const;
    const String& schemeSpecificPart() const;
    const String& authority() const;
    const String& userInfo() const;
    const String& host() const;
    int port() const;
    const String& path() const;
    const String& query() const;
    const String& fragment() const;

    String toString() const;

    bool isAbsolute() const;

protected:
    String  m_strScheme;
    String  m_strSchemeSpecificPart;
    String  m_strAuthority;
    String  m_strUserInfo;
    String  m_strHost;
    int     m_nPort;
    String  m_strPath;
    String  m_strQuery;
    String  m_strFragment;

    String  m_strURI;

    void parse(const char* pszURI)
        __DCL_THROWS1(URISyntaxException*);

    void assign(
        const char* pszScheme,
        const char* pszUserInfo,
        const char* pszHost,
        int nPort,
        const char* pszPath,
        const char* pszQuery,
        const char* pszFragment
        ) __DCL_THROWS1(URISyntaxException*);
};

class DCLNAPI URISyntaxException : public Exception
{
    DECLARE_CLASSINFO(URISyntaxException)
public:
    URISyntaxException(const String& strReason, const String& strSource);
    virtual String getMessage() const;

protected:
    String  m_strMessage;
};

inline const String& URI::scheme() const
{
    return m_strScheme;
}

inline const String& URI::schemeSpecificPart() const
{
    return m_strSchemeSpecificPart;
}

inline const String& URI::authority() const
{
    return m_strAuthority;
}

inline const String& URI::userInfo() const
{
    return m_strUserInfo;
}

inline const String& URI::host() const
{
    return m_strHost;
}

inline int URI::port() const
{
    return m_nPort;
}

inline const String& URI::path() const
{
    return m_strPath;
}

inline const String& URI::query() const
{
    return m_strQuery;
}

inline const String& URI::fragment() const
{
    return m_strFragment;
}

inline String URI::toString() const
{
    return m_strURI;
}

inline bool URI::isAbsolute() const
{
    return !m_strScheme.isEmpty();
}

__DCL_END_NAMESPACE

#endif  // __DCL_URI_H__