/*
 * Copyright (C) 2009 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. ``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
 * 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 "HistoryPropertyList.h"

#include "HistoryItem.h"
#include <wtf/StringExtras.h>

namespace WebCore {

static const int currentFileVersion = 1;

HistoryPropertyListWriter::HistoryPropertyListWriter()
    : m_dailyVisitCountsKey("D")
    , m_displayTitleKey("displayTitle")
    , m_lastVisitWasFailureKey("lastVisitWasFailure")
    , m_lastVisitWasHTTPNonGetKey("lastVisitWasHTTPNonGet")
    , m_lastVisitedDateKey("lastVisitedDate")
    , m_redirectURLsKey("redirectURLs")
    , m_titleKey("title")
    , m_urlKey("")
    , m_visitCountKey("visitCount")
    , m_weeklyVisitCountsKey("W")
    , m_buffer(0)
{
}

UInt8* HistoryPropertyListWriter::buffer(size_t size)
{
    ASSERT(!m_buffer);
    m_buffer = static_cast<UInt8*>(CFAllocatorAllocate(0, size, 0));
    m_bufferSize = size;
    return m_buffer;
}

RetainPtr<CFDataRef> HistoryPropertyListWriter::releaseData()
{
    UInt8* buffer = m_buffer;
    if (!buffer)
        return 0;
    m_buffer = 0;
    RetainPtr<CFDataRef> data(AdoptCF, CFDataCreateWithBytesNoCopy(0, buffer, m_bufferSize, 0));
    if (!data) {
        CFAllocatorDeallocate(0, buffer);
        return 0;
    }
    return data;
}

void HistoryPropertyListWriter::writeObjects(BinaryPropertyListObjectStream& stream)
{
    size_t outerDictionaryStart = stream.writeDictionaryStart();

    stream.writeString("WebHistoryFileVersion");
    stream.writeString("WebHistoryDates");

    stream.writeInteger(currentFileVersion);
    size_t outerDateArrayStart = stream.writeArrayStart();
    writeHistoryItems(stream);
    stream.writeArrayEnd(outerDateArrayStart);

    stream.writeDictionaryEnd(outerDictionaryStart);
}

void HistoryPropertyListWriter::writeHistoryItem(BinaryPropertyListObjectStream& stream, HistoryItem* item)
{
    size_t itemDictionaryStart = stream.writeDictionaryStart();

    const String& title = item->title();
    const String& displayTitle = item->alternateTitle();
    double lastVisitedDate = item->lastVisitedTime();
    int visitCount = item->visitCount();
    Vector<String>* redirectURLs = item->redirectURLs();
    const Vector<int>& dailyVisitCounts = item->dailyVisitCounts();
    const Vector<int>& weeklyVisitCounts = item->weeklyVisitCounts();

    // keys
    stream.writeString(m_urlKey);
    if (!title.isEmpty())
        stream.writeString(m_titleKey);
    if (!displayTitle.isEmpty())
        stream.writeString(m_displayTitleKey);
    if (lastVisitedDate)
        stream.writeString(m_lastVisitedDateKey);
    if (visitCount)
        stream.writeString(m_visitCountKey);
    if (item->lastVisitWasFailure())
        stream.writeString(m_lastVisitWasFailureKey);
    if (item->lastVisitWasHTTPNonGet())
        stream.writeString(m_lastVisitWasHTTPNonGetKey);
    if (redirectURLs)
        stream.writeString(m_redirectURLsKey);
    if (!dailyVisitCounts.isEmpty())
        stream.writeString(m_dailyVisitCountsKey);
    if (!weeklyVisitCounts.isEmpty())
        stream.writeString(m_weeklyVisitCountsKey);

    // values
    stream.writeUniqueString(item->urlString());
    if (!title.isEmpty())
        stream.writeString(title);
    if (!displayTitle.isEmpty())
        stream.writeString(displayTitle);
    if (lastVisitedDate) {
        char buffer[32];
        snprintf(buffer, sizeof(buffer), "%.1lf", lastVisitedDate);
        stream.writeUniqueString(buffer);
    }
    if (visitCount)
        stream.writeInteger(visitCount);
    if (item->lastVisitWasFailure())
        stream.writeBooleanTrue();
    if (item->lastVisitWasHTTPNonGet()) {
        ASSERT(item->urlString().startsWith("http:", false) || item->urlString().startsWith("https:", false));
        stream.writeBooleanTrue();
    }
    if (redirectURLs) {
        size_t redirectArrayStart = stream.writeArrayStart();
        size_t size = redirectURLs->size();
        ASSERT(size);
        for (size_t i = 0; i < size; ++i)
            stream.writeUniqueString(redirectURLs->at(i));
        stream.writeArrayEnd(redirectArrayStart);
    }
    if (size_t size = dailyVisitCounts.size())
        stream.writeIntegerArray(dailyVisitCounts.data(), size);
    if (size_t size = weeklyVisitCounts.size())
        stream.writeIntegerArray(weeklyVisitCounts.data(), size);

    stream.writeDictionaryEnd(itemDictionaryStart);
}

}
