//
// InternetTextMessageHeader.h
//

#define DBG_LEVEL 3
#include <Raym/Log.h>
#include "net/InternetTextMessageHeader.h"

using namespace Raym;

namespace NET
{

InternetTextMessageHeader::InternetTextMessageHeader()
{
    _encoding = ASCIIStringEncoding;
    _fields = NULL;
    _data = NULL;
}

InternetTextMessageHeader::~InternetTextMessageHeader()
{
    RELEASE(_fields);
    RELEASE(_data);
}

InternetTextMessageHeader *InternetTextMessageHeader::alloc()
{
    return new InternetTextMessageHeader();
}

InternetTextMessageHeader *InternetTextMessageHeader::init()
{
    RELEASE(_fields);
    RELEASE(_data);
    _fields = Dictionary::alloc()->initWithCapacity(0);
    return this;
}

InternetTextMessageHeader *InternetTextMessageHeader::initWithData(Data *data)
{
    DebugLog2("%s()\n", __FUNCTION__);

    init();

    if (data != NULL)
    {
        _data = data->retain();

        char field[512];
        const char *buffer = (const char *)data->bytes();

        int index = 0;
        uint offset = 0;
        while (offset < data->length())
        {
            field[index++] = buffer[offset++];
            if ((field[index - 2] == '\r') && (field[index - 1] == '\n'))
            {
                field[index - 2] = '\0';
                char *value = strchr(field, ':');
                if (value != NULL)
                {
                    *value++ = '\0';
                    while (*value == ' ')
                    {
                        ++value;
                    }

                    DebugLog3("%s: %s", field, value);
                    String *body = String::stringWithUTF8String(value);
                    String *name = String::stringWithUTF8String(field);
                    setFieldBodyWithName(body, name);
                }

                index = 0;
            }
        }
    }
    return this;
/*
        char *tmp = (char *)malloc([data length] + 1);
        [data getBytes:tmp length:[data length]];
        tmp[[data length]] = '\0';
        String *headStr = [String stringWithCString:tmp encoding:_encoding];
        if ([headStr rangeOfString:@"content-type" options:CaseInsensitiveSearch].location != NotFound)
        {
            if ([headStr rangeOfString:@"charset" options:CaseInsensitiveSearch].location != NotFound)
            {
                if ([headStr rangeOfString:@"iso-2022-jp" options:CaseInsensitiveSearch].location != NotFound)
                {
                    _encoding = ISO2022JPStringEncoding;
                }
                else if ([headStr rangeOfString:@"shift_jis" options:CaseInsensitiveSearch].location != NotFound)
                {
                    _encoding = ShiftJISStringEncoding;
                }
                else if ([headStr rangeOfString:@"euc-jp" options:CaseInsensitiveSearch].location != NotFound)
                {
                    _encoding = JapaneseEUCStringEncoding;
                }
                else if ([headStr rangeOfString:@"utf-8" options:CaseInsensitiveSearch].location != NotFound)
                {
                    _encoding = UTF8StringEncoding;
                }
            }
        }
*/
}

InternetTextMessageHeader *InternetTextMessageHeader::initWithArray(Array *array)
{
    /*
    if ((self = [super init]) != nil)
    {
        _dictionary = [[MutableDictionary alloc] initWithCapacity:0];
        _encoding = ASCIIStringEncoding;
        for (int i = 0; i < [array count]; ++i)
        {
            String *line = [array objectAtIndex:i];
            Range r = [line rangeOfString:@":"];
            if (r.location != NotFound)
            {
                String *fieldName = [line substringToIndex:r.location];
                String *fieldBody = [[line substringFromIndex:(r.location + 1)] stringByTrimmingCharactersInSet:[CharacterSet whitespaceAndNewlineCharacterSet]];
                [_dictionary setObject:fieldBody forKey:fieldName];
            }
        }
    }
    return self;
    */
    return this;
}

InternetTextMessageHeader *InternetTextMessageHeader::initWithSocket(SOCKET sock)
{
    DebugLog2("%s()\n", __FUNCTION__);

    char *tmp = "\r\n\r\n";

    int length = 0;
    char buf[16384];

    while (length < sizeof(buf))
    {
        char c;
        if (recv(sock, &c, 1, 0) == 1)
        {
            buf[length++] = c;
            if (length >= 4)
            {
                if (strncmp(&buf[length - 4], tmp, 4) == 0)
                {
                    Data *data = Data::alloc()->initWithBytesAndLength(buf, length);
                    initWithData(data);
                    data->release();
                    break;
                }
            }
        }
        else
        {
            // EOF or error
            break;
        }
    }
    return this;
}

/*
- (StringEncoding)encoding
{
    return _encoding;
}
*/

InternetTextMessageHeader *InternetTextMessageHeader::retain()
{
    Object::retain();
    return this;
}

InternetTextMessageHeader *InternetTextMessageHeader::autorelease()
{
    Object::autorelease();
    return this;
}

Array *InternetTextMessageHeader::fieldNames()
{
    return _fields->allKeys();
}

String *InternetTextMessageHeader::fieldBodyForName(String *name)
{
    return (String *)_fields->objectForKey(name);
}

String *InternetTextMessageHeader::fieldBodyForName(const char *name)
{
    return (String *)_fields->objectForKey(name);
}

void InternetTextMessageHeader::setFieldBodyWithName(String *body, String *name)
{
    _fields->setObject(body, name);
    /*
    if ([[name lowercaseString] isEqualToString:@"content-type"])
    {
        if ([body rangeOfString:@"charset" options:CaseInsensitiveSearch].location != NotFound)
        {
            if ([body rangeOfString:@"iso-2022-jp" options:CaseInsensitiveSearch].location != NotFound)
            {
                _encoding = ISO2022JPStringEncoding;
            }
            else if ([body rangeOfString:@"shift_jis" options:CaseInsensitiveSearch].location != NotFound)
            {
                _encoding = ShiftJISStringEncoding;
            }
            else if ([body rangeOfString:@"euc-jp" options:CaseInsensitiveSearch].location != NotFound)
            {
                _encoding = JapaneseEUCStringEncoding;
            }
            else if ([body rangeOfString:@"utf-8" options:CaseInsensitiveSearch].location != NotFound)
            {
                _encoding = UTF8StringEncoding;
            }
        }
    }
    */
}

void InternetTextMessageHeader::setFieldBodyWithName(const char *body, String *name)
{
    setFieldBodyWithName(String::stringWithUTF8String(body), name);
}

void InternetTextMessageHeader::setFieldBodyWithName(String *body, const char *name)
{
    setFieldBodyWithName(body, String::stringWithUTF8String(name));
}

void InternetTextMessageHeader::setFieldBodyWithName(const char *body, const char *name)
{
    setFieldBodyWithName(String::stringWithUTF8String(body), String::stringWithUTF8String(name));
}

Data *InternetTextMessageHeader::data()
{
    /*
    MutableString *headerString = [MutableString stringWithCapacity:0];
    Array *fieldNames = [_dictionary allKeys];

    // Content-type
    for (int i = 0; i < [fieldNames count]; ++i)
    {
        String *fieldName = [fieldNames objectAtIndex:i];
        if ([[fieldName lowercaseString] isEqualToString:@"content-type"])
        {
            [headerString appendFormat:@"Content-type: %@\r\n", [_dictionary objectForKey:fieldName]];
            break;
        }
    }

    // other
    for (int i = 0; i < [fieldNames count]; ++i)
    {
        String *fieldName = [fieldNames objectAtIndex:i];
        String *lowercase = [fieldName lowercaseString];
        if (![lowercase isEqualToString:@"content-type"])
        {
            [headerString appendFormat:@"%@: %@\r\n", fieldName, [_dictionary objectForKey:fieldName]];
        }
    }

    [headerString appendString:@"\r\n\r\n"];

    return [Data dataWithBytes:[headerString cStringUsingEncoding:_encoding] length:[headerString lengthOfBytesUsingEncoding:_encoding]];
    */
    return NULL;
}

const char *InternetTextMessageHeader::className()
{
    return "NET::InternetTextMessageHeader";
}

} // NET
