//
// String.h
//

#ifndef __RAYM_STRING_H__
#define __RAYM_STRING_H__

#include <string>
#include <stdarg.h>
#include <Raym/Object.h>

namespace Raym
{

enum StringEncoding
{
    ASCIIStringEncoding = 1,          /* 0..127 only */
    NEXTSTEPStringEncoding = 2,
    JapaneseEUCStringEncoding = 3,
    UTF8StringEncoding = 4,
    ISOLatin1StringEncoding = 5,
    SymbolStringEncoding = 6,
    NonLossyASCIIStringEncoding = 7,
    ShiftJISStringEncoding = 8,          /* kCFStringEncodingDOSJapanese */
    ISOLatin2StringEncoding = 9,
    UnicodeStringEncoding = 10,
    WindowsCP1251StringEncoding = 11,    /* Cyrillic; same as AdobeStandardCyrillic */
    WindowsCP1252StringEncoding = 12,    /* WinLatin1 */
    WindowsCP1253StringEncoding = 13,    /* Greek */
    WindowsCP1254StringEncoding = 14,    /* Turkish */
    WindowsCP1250StringEncoding = 15,    /* WinLatin2 */
    ISO2022JPStringEncoding = 21,        /* ISO 2022 Japanese encoding for e-mail */
    MacOSRomanStringEncoding = 30,

    UTF16StringEncoding = UnicodeStringEncoding,      /* An alias for UnicodeStringEncoding */

    UTF16BigEndianStringEncoding = 0x90000100,          /* UTF16StringEncoding encoding with explicit endianness specified */
    UTF16LittleEndianStringEncoding = 0x94000100,       /* UTF16StringEncoding encoding with explicit endianness specified */

    UTF32StringEncoding = 0x8c000100,
    UTF32BigEndianStringEncoding = 0x98000100,          /* UTF32StringEncoding encoding with explicit endianness specified */
    UTF32LittleEndianStringEncoding = 0x9c000100        /* UTF32StringEncoding encoding with explicit endianness specified */
};

class Array;
class Data;

class String : public Object
{
protected:
    String();
    ~String();

    char * _str;
    unsigned int _length;

    String *initWithFormat(const char *format, va_list ap);

    friend void Log(const char *format, ...);

public:
    String(const char *str);
    static String *alloc();
    static String *string();
    static String *stringWithCString(const char *nullTerminatedCString, StringEncoding encoding);
    static String *stringWithUTF8String(const char *bytes);
    static String *stringWithFormat(String *format, ...);
    static String *stringWithFormat(const char *format, ...);
    static String *stringWithContentsOfFile(const char *path, StringEncoding encoding);
    static String *stringWithString(String *string);
    static String *base64StringWithBytes(const char *bytes, UInteger length);
    String *init();
    String *initWithCString(const char *nullTerminatedCString, StringEncoding encoding);
    String *initWithData(Data *data, StringEncoding encoding);
    String *initWithUTF8String(const char *bytes);
    String *initWithFormat(const char *format, ...);
    String *retain();
    String *autorelease();

    UInteger length();

    String *stringByAppendingPathComponent(String *pathComponent);
    String *stringByAppendingPathComponent(const char *pathComponent);
    String *stringByAppendingString(String *aString);
    String *stringByAppendingString(const char *aString);
    String *stringByAbbreviatingWithTildeInPath();
    String *stringByReplacingOccurrencesOfString(String *target, String *replacement);
    String *stringByReplacingOccurrencesOfString(const char *target, const char *replacement);
    String *stringByReplacingOccurrencesOfString(const char *target, String *replacement);
    String *stringByStandardizingPath();
    String *stringByRemovingPercentEncoding();
    String *stringByTrimming();

    Array *pathComponents();
    String *pathExtension();

    Array *componentsSeparatedByString(String *separator);
    Array *componentsSeparatedByString(const char *separator);

    String *substringFromIndex(UInteger anIndex);
    String *substringToIndex(UInteger anIndex);

    String *lowercaseString();

    Range rangeOfString(String *aString);
    Range rangeOfString(const char *aString);

    int intValue();

    bool hasPrefix(String *prefix);
    bool hasPrefix(const char *prefix);
    bool hasSuffix(String *suffix);
    bool hasSuffix(const char *suffix);
    bool isEqualToString(String *string);
    bool isEqualToString(const char *string);
    bool isMatch(String *regex);
    bool isMatch(const char *regex);

    const char *cString();

    virtual String *description();
    virtual const char *className();
};

} // Raym

#endif // __RAYM_STRING_H__
