/*
 * Copyright (C) 2010, 2011 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "Download.h"

#include "DataReference.h"

#pragma warning(push, 0)
#include <WebCore/DownloadBundle.h>
#include <WebCore/LoaderRunLoopCF.h>
#include <WebCore/NotImplemented.h>
#include <WebCore/ResourceError.h>
#include <WebCore/ResourceHandle.h>
#include <WebCore/ResourceResponse.h>
#pragma warning(pop)

using namespace WebCore;

namespace WebKit {

// CFURLDownload Callbacks ----------------------------------------------------------------
static void didStartCallback(CFURLDownloadRef download, const void* clientInfo);
static CFURLRequestRef willSendRequestCallback(CFURLDownloadRef download, CFURLRequestRef request, CFURLResponseRef redirectionResponse, const void* clientInfo);
static void didReceiveAuthenticationChallengeCallback(CFURLDownloadRef download, CFURLAuthChallengeRef challenge, const void* clientInfo);
static void didReceiveResponseCallback(CFURLDownloadRef download, CFURLResponseRef response, const void* clientInfo);
static void willResumeWithResponseCallback(CFURLDownloadRef download, CFURLResponseRef response, UInt64 startingByte, const void* clientInfo);
static void didReceiveDataCallback(CFURLDownloadRef download, CFIndex length, const void* clientInfo);
static Boolean shouldDecodeDataOfMIMETypeCallback(CFURLDownloadRef download, CFStringRef encodingType, const void* clientInfo);
static void decideDestinationWithSuggestedObjectNameCallback(CFURLDownloadRef download, CFStringRef objectName, const void* clientInfo);
static void didCreateDestinationCallback(CFURLDownloadRef download, CFURLRef path, const void* clientInfo);
static void didFinishCallback(CFURLDownloadRef download, const void* clientInfo);
static void didFailCallback(CFURLDownloadRef download, CFErrorRef error, const void* clientInfo);

void Download::start(WebPage*)
{
    ASSERT(!m_download);

    CFURLRequestRef cfRequest = m_request.cfURLRequest();

    CFURLDownloadClient client = {0, this, 0, 0, 0, didStartCallback, willSendRequestCallback, didReceiveAuthenticationChallengeCallback, 
                                  didReceiveResponseCallback, willResumeWithResponseCallback, didReceiveDataCallback, shouldDecodeDataOfMIMETypeCallback, 
                                  decideDestinationWithSuggestedObjectNameCallback, didCreateDestinationCallback, didFinishCallback, didFailCallback};
    m_download.adoptCF(CFURLDownloadCreate(0, cfRequest, &client));

    // FIXME: Allow this to be changed by the client.
    CFURLDownloadSetDeletesUponFailure(m_download.get(), false);

    CFURLDownloadScheduleWithCurrentMessageQueue(m_download.get());
    CFURLDownloadScheduleDownloadWithRunLoop(m_download.get(), loaderRunLoop(), kCFRunLoopDefaultMode);

    CFURLDownloadStart(m_download.get());
}

void Download::startWithHandle(WebPage*, ResourceHandle* handle, const ResourceRequest& initialRequest, const ResourceResponse& response)
{
    ASSERT(!m_download);

    CFURLConnectionRef connection = handle->connection();
    if (!connection)
        return;

    CFURLDownloadClient client = {0, this, 0, 0, 0, didStartCallback, willSendRequestCallback, didReceiveAuthenticationChallengeCallback, 
                                  didReceiveResponseCallback, willResumeWithResponseCallback, didReceiveDataCallback, shouldDecodeDataOfMIMETypeCallback,
                                  decideDestinationWithSuggestedObjectNameCallback, didCreateDestinationCallback, didFinishCallback, didFailCallback};

    m_download.adoptCF(CFURLDownloadCreateAndStartWithLoadingConnection(0, connection, initialRequest.cfURLRequest(), response.cfURLResponse(), &client));

    // It is possible for CFURLDownloadCreateAndStartWithLoadingConnection() to fail if the passed in CFURLConnection is not in a "downloadable state"
    // However, we should never hit that case
    if (!m_download)
        ASSERT_NOT_REACHED();

    // The CFURLDownload either starts successfully and retains the CFURLConnection, 
    // or it fails to creating and we have a now-useless connection with a dangling ref. 
    // Either way, we need to release the connection to balance out ref counts
    handle->releaseConnectionForDownload();
    CFRelease(connection);
}

void Download::cancel()
{
    ASSERT(m_download);
    if (!m_download)
        return;

    CFURLDownloadSetDeletesUponFailure(m_download.get(), false);
    CFURLDownloadCancel(m_download.get());

    RetainPtr<CFDataRef> resumeData(AdoptCF, CFURLDownloadCopyResumeData(m_download.get()));
    if (resumeData)
        DownloadBundle::appendResumeData(resumeData.get(), m_bundlePath);

    didCancel(CoreIPC::DataReference());
}

void Download::platformInvalidate()
{
    m_download = nullptr;
}

void Download::didDecideDestination(const String& destination, bool allowOverwrite)
{
    ASSERT(!destination.isEmpty());
    if (destination.isEmpty())
        return;

    m_allowOverwrite = allowOverwrite;
    m_destination = destination;
    m_bundlePath = destination + DownloadBundle::fileExtension();

    RetainPtr<CFStringRef> bundlePath(AdoptCF, CFStringCreateWithCharactersNoCopy(0, reinterpret_cast<const UniChar*>(m_bundlePath.characters()), m_bundlePath.length(), kCFAllocatorNull));
    RetainPtr<CFURLRef> bundlePathURL(AdoptCF, CFURLCreateWithFileSystemPath(0, bundlePath.get(), kCFURLWindowsPathStyle, false));
    CFURLDownloadSetDestination(m_download.get(), bundlePathURL.get(), allowOverwrite);
}

// CFURLDownload Callbacks ----------------------------------------------------------------
static Download* downloadFromClientInfo(const void* clientInfo)
{
    return reinterpret_cast<Download*>(const_cast<void*>(clientInfo));
}

void didStartCallback(CFURLDownloadRef, const void* clientInfo)
{ 
    downloadFromClientInfo(clientInfo)->didStart(); 
}

CFURLRequestRef willSendRequestCallback(CFURLDownloadRef, CFURLRequestRef request, CFURLResponseRef redirectionResponse, const void* clientInfo)
{ 
    // CFNetwork requires us to return a retained request.
    CFRetain(request);
    return request;
}

void didReceiveAuthenticationChallengeCallback(CFURLDownloadRef, CFURLAuthChallengeRef challenge, const void* clientInfo)
{ 
    // FIXME: implement.
    notImplemented();
}

void didReceiveResponseCallback(CFURLDownloadRef, CFURLResponseRef response, const void* clientInfo)
{
    downloadFromClientInfo(clientInfo)->didReceiveResponse(ResourceResponse(response)); 
}

void willResumeWithResponseCallback(CFURLDownloadRef, CFURLResponseRef response, UInt64 startingByte, const void* clientInfo)
{
    // FIXME: implement.
    notImplemented();
}

void didReceiveDataCallback(CFURLDownloadRef, CFIndex length, const void* clientInfo)
{ 
    downloadFromClientInfo(clientInfo)->didReceiveData(length);
}

Boolean shouldDecodeDataOfMIMETypeCallback(CFURLDownloadRef, CFStringRef encodingType, const void* clientInfo)
{ 
    return downloadFromClientInfo(clientInfo)->shouldDecodeSourceDataOfMIMEType(encodingType);
}

void decideDestinationWithSuggestedObjectNameCallback(CFURLDownloadRef, CFStringRef objectName, const void* clientInfo)
{ 
    Download* download = downloadFromClientInfo(clientInfo);
    bool allowOverwrite;
    download->decideDestinationWithSuggestedFilename(objectName, allowOverwrite);
}

void didCreateDestinationCallback(CFURLDownloadRef, CFURLRef, const void* clientInfo)
{
    // The concept of the ".download bundle" is internal to the Download, so we try to hide its
    // existence by reporting the final destination was created, when in reality the bundle was created.

    Download* download = downloadFromClientInfo(clientInfo);
    download->didCreateDestination(download->destination());
}

void didFinishCallback(CFURLDownloadRef, const void* clientInfo)
{ 
    downloadFromClientInfo(clientInfo)->didFinish();
}

void didFailCallback(CFURLDownloadRef, CFErrorRef error, const void* clientInfo)
{ 
    CoreIPC::DataReference dataReference(0, 0);
    downloadFromClientInfo(clientInfo)->didFail(ResourceError(error), dataReference);
}

void Download::receivedCredential(const AuthenticationChallenge& authenticationChallenge, const Credential& credential)
{
    notImplemented();
}

void Download::receivedRequestToContinueWithoutCredential(const AuthenticationChallenge& authenticationChallenge)
{
    notImplemented();
}

void Download::receivedCancellation(const AuthenticationChallenge& authenticationChallenge)
{
    notImplemented();
}

} // namespace WebKit
