/*
 * Copyright (C) 2012 Igalia S.L.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "config.h"
#include "WebKitSoupRequestGeneric.h"

#include "WebProcess.h"
#include "WebSoupRequestManager.h"
#include <wtf/text/CString.h>

using namespace WebKit;

G_DEFINE_TYPE(WebKitSoupRequestGeneric, webkit_soup_request_generic, SOUP_TYPE_REQUEST)

struct _WebKitSoupRequestGenericPrivate {
    CString mimeType;
    goffset contentLength;
};

static void webkitSoupRequestGenericFinalize(GObject* object)
{
    WEBKIT_SOUP_REQUEST_GENERIC(object)->priv->~WebKitSoupRequestGenericPrivate();
    G_OBJECT_CLASS(webkit_soup_request_generic_parent_class)->finalize(object);
}

static void webkit_soup_request_generic_init(WebKitSoupRequestGeneric* request)
{
    WebKitSoupRequestGenericPrivate* priv = G_TYPE_INSTANCE_GET_PRIVATE(request, WEBKIT_TYPE_SOUP_REQUEST_GENERIC, WebKitSoupRequestGenericPrivate);
    request->priv = priv;
    new (priv) WebKitSoupRequestGenericPrivate();
}

static void webkitSoupRequestGenericSendAsync(SoupRequest* request, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
{
    GSimpleAsyncResult* result = g_simple_async_result_new(G_OBJECT(request), callback, userData, reinterpret_cast<void*>(webkitSoupRequestGenericSendAsync));
    WebProcess::shared().supplement<WebSoupRequestManager>()->send(result, cancellable);
}

static GInputStream* webkitSoupRequestGenericSendFinish(SoupRequest*, GAsyncResult* result, GError** error)
{
    GSimpleAsyncResult* simpleResult = G_SIMPLE_ASYNC_RESULT(result);
    g_warn_if_fail(g_simple_async_result_get_source_tag(simpleResult) == webkitSoupRequestGenericSendAsync);

    if (g_simple_async_result_propagate_error(simpleResult, error))
        return 0;

    return WebProcess::shared().supplement<WebSoupRequestManager>()->finish(simpleResult);
}

static goffset webkitSoupRequestGenericGetContentLength(SoupRequest* request)
{
    return WEBKIT_SOUP_REQUEST_GENERIC(request)->priv->contentLength;
}

static const char* webkitSoupRequestGenericGetContentType(SoupRequest* request)
{
    return WEBKIT_SOUP_REQUEST_GENERIC(request)->priv->mimeType.data();
}

static void webkit_soup_request_generic_class_init(WebKitSoupRequestGenericClass* requestGenericClass)
{
    GObjectClass* gObjectClass = G_OBJECT_CLASS(requestGenericClass);
    gObjectClass->finalize = webkitSoupRequestGenericFinalize;

    SoupRequestClass* requestClass = SOUP_REQUEST_CLASS(requestGenericClass);
    requestClass->send_async = webkitSoupRequestGenericSendAsync;
    requestClass->send_finish = webkitSoupRequestGenericSendFinish;
    requestClass->get_content_length = webkitSoupRequestGenericGetContentLength;
    requestClass->get_content_type = webkitSoupRequestGenericGetContentType;

    g_type_class_add_private(requestGenericClass, sizeof(WebKitSoupRequestGenericPrivate));
}

void webkitSoupRequestGenericSetContentLength(WebKitSoupRequestGeneric* request, goffset contentLength)
{
    request->priv->contentLength = contentLength;
}

void webkitSoupRequestGenericSetContentType(WebKitSoupRequestGeneric* request, const char* mimeType)
{
    request->priv->mimeType = mimeType;
}
