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

#include "DOMCoreClasses.h"
#include "WebElementPropertyBag.h"
#include "WebKit.h"
#include <WebCore/BString.h>
#include <WebCore/COMPtr.h>
#include <WebCore/EventHandler.h>
#include <WebCore/HitTestResult.h>
#include <WebCore/MouseEvent.h>

using namespace WebCore;

// WebActionPropertyBag ------------------------------------------------

WebActionPropertyBag::WebActionPropertyBag(const NavigationAction& action, RefPtr<HTMLFormElement>&& form, RefPtr<Frame>&& frame)
    : m_action(action)
    , m_form(WTFMove(form))
    , m_frame(WTFMove(frame))
{
    gClassCount++;
    gClassNameCount().add("WebActionPropertyBag"_s);
}

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

WebActionPropertyBag* WebActionPropertyBag::createInstance(const NavigationAction& action, RefPtr<HTMLFormElement>&& form, RefPtr<Frame>&& frame)
{
    WebActionPropertyBag* instance = new WebActionPropertyBag(action, WTFMove(form), WTFMove(frame));
    instance->AddRef();
    return instance;
}

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

HRESULT WebActionPropertyBag::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 WebActionPropertyBag::AddRef()
{
    return ++m_refCount;
}

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

    return newRef;
}

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

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

    ::VariantClear(pVar);

    if (isEqual(pszPropName, WebActionNavigationTypeKey)) {
        V_VT(pVar) = VT_I4;
        V_I4(pVar) = static_cast<LONG>(m_action.type());
        return S_OK;
    }
    if (isEqual(pszPropName, WebActionElementKey)) {
        if (auto mouseEvent = m_action.mouseEventData()) {
            V_VT(pVar) = VT_UNKNOWN;
            constexpr OptionSet<HitTestRequest::Type> hitType { HitTestRequest::Type::ReadOnly, HitTestRequest::Type::Active, HitTestRequest::Type::DisallowUserAgentShadowContent, HitTestRequest::Type::AllowChildFrameContent };
            V_UNKNOWN(pVar) = WebElementPropertyBag::createInstance(m_frame->eventHandler().hitTestResultAtPoint(mouseEvent->absoluteLocation, hitType));
            return S_OK;
        }
    }
    if (isEqual(pszPropName, WebActionButtonKey)) {
        if (auto mouseEvent = m_action.mouseEventData()) {
            V_VT(pVar) = VT_I4;
            V_I4(pVar) = mouseEvent->button;
            return S_OK;
        }
    }
    if (isEqual(pszPropName, WebActionOriginalURLKey)) {
        V_VT(pVar) = VT_BSTR;
        V_BSTR(pVar) = BString(m_action.url().string()).release();
        return S_OK;
    }
    if (isEqual(pszPropName, WebActionModifierFlagsKey)) {
        if (auto keyEvent = m_action.keyStateEventData()) {
            unsigned modifiers = 0;

            if (keyEvent->ctrlKey)
                modifiers |= MK_CONTROL;
            if (keyEvent->shiftKey)
                modifiers |= MK_SHIFT;
            if (keyEvent->altKey)
                modifiers |= MK_ALT;

            V_VT(pVar) = VT_UI4;
            V_UI4(pVar) = modifiers;
            return S_OK;
        }
    }
    if (isEqual(pszPropName, WebActionFormKey)) {
        IDOMNode* form = DOMNode::createInstance(m_form.get());
        V_VT(pVar) = VT_UNKNOWN;
        V_UNKNOWN(pVar) = form;
        return S_OK;
    }
    return E_INVALIDARG;
}

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

    return E_NOTIMPL;
}
