/*
 * Copyright (C) 2006-2008, 2015 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 "WebKitDLL.h"
#include "WebHistoryItem.h"

#include "COMEnumVariant.h"
#include "MarshallingHelpers.h"
#include "WebKit.h"
#include <WebCore/BString.h>
#include <WebCore/COMPtr.h>
#include <WebCore/HistoryItem.h>
#include <wtf/RetainPtr.h>
#include <wtf/URL.h>
#include <wtf/text/CString.h>

using namespace WebCore;

// WebHistoryItem ----------------------------------------------------------------

static HashMap<HistoryItem*, WebHistoryItem*>& historyItemWrappers()
{
    static HashMap<HistoryItem*, WebHistoryItem*> staticHistoryItemWrappers;
    return staticHistoryItemWrappers;
}

WebHistoryItem::WebHistoryItem(RefPtr<HistoryItem>&& historyItem)
    : m_historyItem(WTFMove(historyItem))
{
    ASSERT(!historyItemWrappers().contains(m_historyItem.get()));
    historyItemWrappers().set(m_historyItem.get(), this);

    gClassCount++;
    gClassNameCount().add("WebHistoryItem"_s);
}

WebHistoryItem::~WebHistoryItem()
{
    ASSERT(historyItemWrappers().contains(m_historyItem.get()));
    historyItemWrappers().remove(m_historyItem.get());

    gClassCount--;
    gClassNameCount().remove("WebHistoryItem"_s);
}

WebHistoryItem* WebHistoryItem::createInstance()
{
    WebHistoryItem* instance = new WebHistoryItem(HistoryItem::create());
    instance->AddRef();
    return instance;
}

WebHistoryItem* WebHistoryItem::createInstance(RefPtr<HistoryItem>&& historyItem)
{
    WebHistoryItem* instance;

    instance = historyItemWrappers().get(historyItem.get());

    if (!instance)
        instance = new WebHistoryItem(WTFMove(historyItem));

    instance->AddRef();
    return instance;
}

// IWebHistoryItemPrivate -----------------------------------------------------

#if USE(CF)
static CFStringRef urlKey = CFSTR("");
static CFStringRef titleKey = CFSTR("title");
static CFStringRef lastVisitWasFailureKey = CFSTR("lastVisitWasFailure");
static CFStringRef redirectURLsKey = CFSTR("redirectURLs");
#endif

HRESULT WebHistoryItem::initFromDictionaryRepresentation(_In_opt_ void* dictionary)
{
#if USE(CF)
    CFDictionaryRef dictionaryRef = (CFDictionaryRef) dictionary;

    CFStringRef urlStringRef = (CFStringRef) CFDictionaryGetValue(dictionaryRef, urlKey);
    if (urlStringRef && CFGetTypeID(urlStringRef) != CFStringGetTypeID())
        return E_FAIL;

    CFStringRef titleRef = (CFStringRef) CFDictionaryGetValue(dictionaryRef, titleKey);
    if (titleRef && CFGetTypeID(titleRef) != CFStringGetTypeID())
        return E_FAIL;

    CFBooleanRef lastVisitWasFailureRef = static_cast<CFBooleanRef>(CFDictionaryGetValue(dictionaryRef, lastVisitWasFailureKey));
    if (lastVisitWasFailureRef && CFGetTypeID(lastVisitWasFailureRef) != CFBooleanGetTypeID())
        return E_FAIL;
    bool lastVisitWasFailure = lastVisitWasFailureRef && CFBooleanGetValue(lastVisitWasFailureRef);

    std::unique_ptr<Vector<String>> redirectURLsVector;
    if (CFArrayRef redirectURLsRef = static_cast<CFArrayRef>(CFDictionaryGetValue(dictionaryRef, redirectURLsKey))) {
        CFIndex size = CFArrayGetCount(redirectURLsRef);
        redirectURLsVector = makeUnique<Vector<String>>(size);
        for (CFIndex i = 0; i < size; ++i)
            (*redirectURLsVector)[i] = String(static_cast<CFStringRef>(CFArrayGetValueAtIndex(redirectURLsRef, i)));
    }

    historyItemWrappers().remove(m_historyItem.get());
    m_historyItem = HistoryItem::create(urlStringRef, titleRef);
    historyItemWrappers().set(m_historyItem.get(), this);

    if (lastVisitWasFailure)
        m_historyItem->setLastVisitWasFailure(true);

    return S_OK;
#else
    return E_NOTIMPL;
#endif
}

HRESULT WebHistoryItem::dictionaryRepresentation(__deref_out_opt void** dictionary)
{
#if USE(CF)
    CFDictionaryRef* dictionaryRef = (CFDictionaryRef*) dictionary;

    size_t keyCount = 0;
    CFTypeRef keys[9];
    CFTypeRef values[9];

    if (!m_historyItem->urlString().isEmpty()) {
        keys[keyCount] = urlKey;
        values[keyCount] = m_historyItem->urlString().createCFString().leakRef();
        ++keyCount;
    }

    if (!m_historyItem->title().isEmpty()) {
        keys[keyCount] = titleKey;
        values[keyCount] = m_historyItem->title().createCFString().leakRef();
        ++keyCount;
    }

    if (m_historyItem->lastVisitWasFailure()) {
        keys[keyCount] = lastVisitWasFailureKey;
        values[keyCount] = CFRetain(kCFBooleanTrue);
        ++keyCount;
    }

    *dictionaryRef = CFDictionaryCreate(0, keys, values, keyCount, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    
    for (int i = 0; i < keyCount; ++i)
        CFRelease(values[i]);

    return S_OK;
#else
    return E_NOTIMPL;
#endif
}

HRESULT WebHistoryItem::hasURLString(_Out_ BOOL* hasURL)
{
    if (!hasURL)
        return E_POINTER;
    *hasURL = m_historyItem->urlString().isEmpty() ? FALSE : TRUE;
    return S_OK;
}

// FIXME: This function should be removed from the IWebHistoryItem interface.
HRESULT WebHistoryItem::visitCount(_Out_ int* count)
{
    if (!count)
        return E_POINTER;
    return E_NOTIMPL;
}

// FIXME: This function should be removed from the IWebHistoryItem interface.
HRESULT WebHistoryItem::setVisitCount(int count)
{
    return E_NOTIMPL;

}

// FIXME: This function should be removed from the IWebHistoryItem interface.
HRESULT WebHistoryItem::mergeAutoCompleteHints(_In_opt_ IWebHistoryItem*)
{
    return E_NOTIMPL;
}

// FIXME: This function should be removed from the IWebHistoryItem interface.
HRESULT WebHistoryItem::setLastVisitedTimeInterval(DATE time)
{
    return E_NOTIMPL;
}

HRESULT WebHistoryItem::setTitle(_In_ BSTR title)
{
    m_historyItem->setTitle(String(title, SysStringLen(title)));

    return S_OK;
}

HRESULT WebHistoryItem::RSSFeedReferrer(__deref_out_opt BSTR* url)
{
    if (!url)
        return E_POINTER;

    BString str(m_historyItem->referrer());
    *url = str.release();

    return S_OK;
}

HRESULT WebHistoryItem::setRSSFeedReferrer(_In_ BSTR url)
{
    m_historyItem->setReferrer(String(url, SysStringLen(url)));

    return S_OK;
}

HRESULT WebHistoryItem::hasPageCache(_Out_ BOOL* hasCache)
{
    // FIXME - TODO
    ASSERT_NOT_REACHED();
    if (!hasCache)
        return E_POINTER;
    *hasCache = FALSE;
    return E_NOTIMPL;
}

HRESULT WebHistoryItem::setHasPageCache(BOOL /*hasCache*/)
{
    // FIXME - TODO
    ASSERT_NOT_REACHED();
    return E_NOTIMPL;
}

HRESULT WebHistoryItem::target(__deref_out_opt BSTR* target)
{
    if (!target) {
        ASSERT_NOT_REACHED();
        return E_POINTER;
    }

    *target = BString(m_historyItem->target()).release();
    return S_OK;
}

HRESULT WebHistoryItem::isTargetItem(_Out_ BOOL* result)
{
    if (!result) {
        ASSERT_NOT_REACHED();
        return E_POINTER;
    }

    *result = m_historyItem->isTargetItem() ? TRUE : FALSE;
    return S_OK;
}

HRESULT WebHistoryItem::children(unsigned* outChildCount, SAFEARRAY** outChildren)
{
    if (!outChildCount || !outChildren) {
        ASSERT_NOT_REACHED();
        return E_POINTER;
    }

    *outChildCount = 0;
    *outChildren = 0;

    const auto& coreChildren = m_historyItem->children();
    if (coreChildren.isEmpty())
        return S_OK;
    size_t childCount = coreChildren.size();

    SAFEARRAY* children = SafeArrayCreateVector(VT_UNKNOWN, 0, static_cast<ULONG>(childCount));
    if (!children)
        return E_OUTOFMEMORY;

    for (unsigned i = 0; i < childCount; ++i) {
        COMPtr<WebHistoryItem> item(AdoptCOM, WebHistoryItem::createInstance(const_cast<HistoryItem*>(coreChildren[i].ptr())));
        if (!item) {
            SafeArrayDestroy(children);
            return E_OUTOFMEMORY;
        }

        LONG longI = i;
        HRESULT hr = SafeArrayPutElement(children, &longI, item.get());
        if (FAILED(hr)) {
            SafeArrayDestroy(children);
            return hr;
        }
    }

    *outChildCount = static_cast<unsigned>(childCount);
    *outChildren = children;
    return S_OK;

}

HRESULT WebHistoryItem::lastVisitWasFailure(_Out_ BOOL* wasFailure)
{
    if (!wasFailure) {
        ASSERT_NOT_REACHED();
        return E_POINTER;
    }

    *wasFailure = m_historyItem->lastVisitWasFailure();
    return S_OK;
}

HRESULT WebHistoryItem::setLastVisitWasFailure(BOOL wasFailure)
{
    m_historyItem->setLastVisitWasFailure(wasFailure);
    return S_OK;
}

// FIXME: This function should be removed from the IWebHistoryItem interface.
HRESULT WebHistoryItem::lastVisitWasHTTPNonGet(_Out_ BOOL* HTTPNonGet)
{
    if (!HTTPNonGet)
        return E_POINTER;
    *HTTPNonGet = FALSE;
    return E_NOTIMPL;
}

// FIXME: This function should be removed from the IWebHistoryItem interface.
HRESULT WebHistoryItem::setLastVisitWasHTTPNonGet(BOOL)
{
    return E_NOTIMPL;
}

// FIXME: This function should be removed from the IWebHistoryItem interface.
HRESULT WebHistoryItem::redirectURLs(_COM_Outptr_opt_ IEnumVARIANT** urls)
{
    return E_NOTIMPL;
}

// FIXME: This function should be removed from the IWebHistoryItem interface.
HRESULT WebHistoryItem::visitedWithTitle(_In_ BSTR title, BOOL increaseVisitCount)
{
    return E_NOTIMPL;
}

// FIXME: This function should be removed from the IWebHistoryItem interface.
HRESULT WebHistoryItem::getDailyVisitCounts(_Out_ int* number, __deref_out_opt int** counts)
{
    if (!number || !counts)
        return E_POINTER;
    return E_NOTIMPL;
}

// FIXME: This function should be removed from the IWebHistoryItem interface.
HRESULT WebHistoryItem::getWeeklyVisitCounts(_Out_ int* number, __deref_out_opt int** counts)
{
    if (!number || !counts)
        return E_POINTER;
    return E_NOTIMPL;
}

// FIXME: This function should be removed from the IWebHistoryItem interface.
HRESULT WebHistoryItem::recordInitialVisit()
{
    // FIXME: This function should be removed from the IWebHistoryItem interface.
    return E_NOTIMPL;
}

// IUnknown -------------------------------------------------------------------

HRESULT WebHistoryItem::QueryInterface(_In_ REFIID riid, _COM_Outptr_ void** ppvObject)
{
    if (!ppvObject)
        return E_POINTER;
    *ppvObject = nullptr;
    if (IsEqualGUID(riid, __uuidof(WebHistoryItem)))
        *ppvObject = this;
    else if (IsEqualGUID(riid, IID_IUnknown))
        *ppvObject = static_cast<IWebHistoryItem*>(this);
    else if (IsEqualGUID(riid, IID_IWebHistoryItem))
        *ppvObject = static_cast<IWebHistoryItem*>(this);
    else if (IsEqualGUID(riid, IID_IWebHistoryItemPrivate))
        *ppvObject = static_cast<IWebHistoryItemPrivate*>(this);
    else
        return E_NOINTERFACE;

    AddRef();
    return S_OK;
}

ULONG WebHistoryItem::AddRef()
{
    return ++m_refCount;
}

ULONG WebHistoryItem::Release()
{
    ULONG newRef = --m_refCount;
    if (!newRef)
        delete(this);

    return newRef;
}

// IWebHistoryItem -------------------------------------------------------------

HRESULT WebHistoryItem::initWithURLString(_In_ BSTR urlString, _In_ BSTR title, DATE lastVisited)
{
    historyItemWrappers().remove(m_historyItem.get());
    m_historyItem = HistoryItem::create(String(urlString, SysStringLen(urlString)), String(title, SysStringLen(title)));
    historyItemWrappers().set(m_historyItem.get(), this);

    return S_OK;
}

HRESULT WebHistoryItem::originalURLString(__deref_opt_out BSTR* url)
{
    if (!url)
        return E_POINTER;

    BString str = m_historyItem->originalURLString();
    *url = str.release();
    return S_OK;
}

HRESULT WebHistoryItem::URLString(__deref_opt_out BSTR* url)
{
    if (!url)
        return E_POINTER;

    BString str = m_historyItem->urlString();
    *url = str.release();
    return S_OK;
}

HRESULT WebHistoryItem::title(__deref_opt_out BSTR* pageTitle)
{
    if (!pageTitle)
        return E_POINTER;

    BString str(m_historyItem->title());
    *pageTitle = str.release();
    return S_OK;
}

// FIXME: This function should be removed from the IWebHistoryItem interface.
HRESULT WebHistoryItem::lastVisitedTimeInterval(_Out_ DATE* lastVisited)
{
    if (!lastVisited)
        return E_POINTER;
    return E_NOTIMPL;
}

HRESULT WebHistoryItem::setAlternateTitle(_In_ BSTR title)
{
    m_alternateTitle = String(title, SysStringLen(title));
    return S_OK;
}

HRESULT WebHistoryItem::alternateTitle(__deref_opt_out BSTR* title)
{
    if (!title) {
        ASSERT_NOT_REACHED();
        return E_POINTER;
    }

    *title = BString(m_alternateTitle).release();
    return S_OK;
}

HRESULT WebHistoryItem::icon(__deref_opt_out HBITMAP* hBitmap)
{
    ASSERT_NOT_REACHED();
    if (!hBitmap)
        return E_POINTER;
    return E_NOTIMPL;
}

// WebHistoryItem -------------------------------------------------------------

HistoryItem* WebHistoryItem::historyItem() const
{
    return m_historyItem.get();
}
