/*
 * Copyright (C) 2006-2007, 2013, 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 "WebElementPropertyBag.h"

#include "MarshallingHelpers.h"
#include "DOMCoreClasses.h"
#include "WebFrame.h"
#include "WebFrameLoaderClient.h"
#include <WebCore/BString.h>
#include <WebCore/Document.h>
#include <WebCore/Frame.h>
#include <WebCore/HitTestResult.h>
#include <WebCore/FrameLoader.h>
#include <WebCore/Image.h>
#include <WebCore/RenderObject.h>
#include <wtf/URL.h>

using namespace WebCore;

// WebElementPropertyBag -----------------------------------------------
WebElementPropertyBag::WebElementPropertyBag(const HitTestResult& result)
    : m_result(makeUnique<HitTestResult>(result))
{
    gClassCount++;
    gClassNameCount().add("WebElementPropertyBag");
}

WebElementPropertyBag::~WebElementPropertyBag()
{
    gClassCount--;
    gClassNameCount().remove("WebElementPropertyBag");
}

WebElementPropertyBag* WebElementPropertyBag::createInstance(const HitTestResult& result)
{
    WebElementPropertyBag* instance = new WebElementPropertyBag(result); 
    instance->AddRef();

    return instance;
}

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

HRESULT WebElementPropertyBag::QueryInterface(_In_ REFIID riid, _COM_Outptr_ void** ppvObject)
{
    if (!ppvObject)
        return E_POINTER;
    *ppvObject = nullptr;
    if (IsEqualGUID(riid, IID_IUnknown))
        *ppvObject = static_cast<IPropertyBag*>(this);
    else if (IsEqualGUID(riid, IID_IPropertyBag))
        *ppvObject = static_cast<IPropertyBag*>(this);
    else
        return E_NOINTERFACE;

    AddRef();
    return S_OK;
}

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

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

    return newRef;
}

static bool isEqual(LPCWSTR s1, LPCWSTR s2)
{
    return !wcscmp(s1, s2);
}

static HRESULT convertStringToVariant(VARIANT* pVar, const String& string)
{
    V_VT(pVar) = VT_BSTR;
    V_BSTR(pVar) = BString(string).release();
    if (string.length() && !V_BSTR(pVar))
        return E_OUTOFMEMORY;

    return S_OK;
}


HRESULT WebElementPropertyBag::Read(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog * /*pErrorLog*/)
{
    if (!pszPropName)
        return E_POINTER;

    if (!m_result)
        return E_FAIL;

    BSTR key = (BSTR)pszPropName;
    ::VariantClear(pVar);
    if (isEqual(WebElementDOMNodeKey, key)) {
        IDOMNode* node = DOMNode::createInstance(m_result->innerNonSharedNode());
        V_VT(pVar) = VT_UNKNOWN;
        V_UNKNOWN(pVar) = node;
        return S_OK;
    } else if (isEqual(WebElementFrameKey, key)) {
        if (!(m_result->innerNonSharedNode() && m_result->innerNonSharedNode()->document().frame()))
            return E_FAIL;
        Frame* coreFrame = m_result->innerNonSharedNode()->document().frame();
        WebFrame* webFrame = static_cast<WebFrameLoaderClient&>(coreFrame->loader().client()).webFrame();
        IWebFrame* iWebFrame;
        if (FAILED(webFrame->QueryInterface(IID_IWebFrame, (void**)&iWebFrame)))
            return E_FAIL;
        V_VT(pVar) = VT_UNKNOWN;
        V_UNKNOWN(pVar) = iWebFrame;
        return S_OK;
    } else if (isEqual(WebElementImageAltStringKey, key))
        return convertStringToVariant(pVar, m_result->altDisplayString());
    else if (isEqual(WebElementImageKey, key)) {
        V_VT(pVar) = VT_BYREF;
        V_BYREF(pVar) = m_result->image();
        return S_OK;
    } else if (isEqual(WebElementImageRectKey, key)) {
        V_VT(pVar) = VT_ARRAY;
        IntRect boundingBox = m_result->innerNonSharedNode() && m_result->innerNonSharedNode()->renderer() ?
                                m_result->innerNonSharedNode()->renderer()->absoluteBoundingBoxRect(true) : IntRect();
        V_ARRAY(pVar) = MarshallingHelpers::intRectToSafeArray(boundingBox);
        return S_OK;
    } else if (isEqual(WebElementImageURLKey, key))
        return convertStringToVariant(pVar, m_result->absoluteImageURL().string());
    else if (isEqual(WebElementIsSelectedKey, key)) {
        V_VT(pVar) = VT_BOOL;
        if (m_result->isSelected())
            V_BOOL(pVar) = VARIANT_TRUE;
        else
            V_BOOL(pVar) = VARIANT_FALSE;
        return S_OK;
    }
    if (isEqual(WebElementMediaURLKey, key))
        return convertStringToVariant(pVar, m_result->absoluteMediaURL().string());
    if (isEqual(WebElementSpellingToolTipKey, key)) {
        TextDirection dir;
        return convertStringToVariant(pVar, m_result->spellingToolTip(dir));
    } else if (isEqual(WebElementTitleKey, key)) {
        TextDirection dir;
        return convertStringToVariant(pVar, m_result->title(dir));
    }
    else if (isEqual(WebElementLinkURLKey, key))
        return convertStringToVariant(pVar, m_result->absoluteLinkURL().string());
    else if (isEqual(WebElementLinkTargetFrameKey, key)) {
        if (!m_result->targetFrame())
            return E_FAIL;
        WebFrame* webFrame = kit(m_result->targetFrame());
        IWebFrame* iWebFrame;
        if (FAILED(webFrame->QueryInterface(IID_IWebFrame, (void**)&iWebFrame)))
            return E_FAIL;
        V_VT(pVar) = VT_UNKNOWN;
        V_UNKNOWN(pVar) = iWebFrame;
        return S_OK;
    } else if (isEqual(WebElementLinkTitleKey, key))
        return convertStringToVariant(pVar, m_result->titleDisplayString());
    else if (isEqual(WebElementLinkLabelKey, key))
        return convertStringToVariant(pVar, m_result->textContent());
    else if (isEqual(WebElementIsContentEditableKey, key)) {
        V_VT(pVar) = VT_BOOL;
        if (m_result->isContentEditable())
            V_BOOL(pVar) = VARIANT_TRUE;
        else
            V_BOOL(pVar) = VARIANT_FALSE;
        return S_OK;
    }

    return E_INVALIDARG;
}

HRESULT WebElementPropertyBag::Write(_In_ LPCOLESTR pszPropName, _In_ VARIANT* pVar)
{
    if (!pszPropName || !pVar)
        return E_POINTER;

    return E_NOTIMPL;
}
