/*
 *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
 *  Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010 Apple Inc. All rights reserved.
 *  Copyright (C) 2007 Samuel Weinig <sam@webkit.org>
 *  Copyright (C) 2009 Google, Inc. All rights reserved.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#pragma once

#include "JSDOMGlobalObject.h"
#include "NodeConstants.h"
#include <runtime/JSDestructibleObject.h>

namespace WebCore {

class JSDOMWindow;
class ScriptExecutionContext;

// We encode Node type into JSType. The format is the following.
// offset | 7 | 6 5 4 | 3 2 1 0  |
// value  | 1 | Kind  | NodeType |
static const uint8_t JSNodeTypeMask                  = 0b00001111;

static const uint8_t JSDOMWrapperType                = 0b10000000;
static const uint8_t JSNodeType                      = 0b10010000;
static const uint8_t JSTextNodeType                  = JSNodeType | NodeConstants::TEXT_NODE;
static const uint8_t JSProcessingInstructionNodeType = JSNodeType | NodeConstants::PROCESSING_INSTRUCTION_NODE;
static const uint8_t JSDocumentTypeNodeType          = JSNodeType | NodeConstants::DOCUMENT_TYPE_NODE;
static const uint8_t JSDocumentFragmentNodeType      = JSNodeType | NodeConstants::DOCUMENT_FRAGMENT_NODE;
static const uint8_t JSDocumentWrapperType           = JSNodeType | NodeConstants::DOCUMENT_NODE;
static const uint8_t JSCommentNodeType               = JSNodeType | NodeConstants::COMMENT_NODE;
static const uint8_t JSCDATASectionNodeType          = JSNodeType | NodeConstants::CDATA_SECTION_NODE;
static const uint8_t JSAttrNodeType                  = JSNodeType | NodeConstants::ATTRIBUTE_NODE;
static const uint8_t JSElementType                   = 0b10100000 | NodeConstants::ELEMENT_NODE;

static_assert(JSDOMWrapperType > JSC::LastJSCObjectType, "JSC::JSType offers the highest bit.");
static_assert(NodeConstants::LastNodeType <= JSNodeTypeMask, "NodeType should be represented in 4bit.");

class JSDOMObject : public JSC::JSDestructibleObject {
public:
    typedef JSC::JSDestructibleObject Base;
    static constexpr bool isDOMWrapper = false;

    JSDOMGlobalObject* globalObject() const { return JSC::jsCast<JSDOMGlobalObject*>(JSC::JSNonFinalObject::globalObject()); }
    ScriptExecutionContext* scriptExecutionContext() const { return globalObject()->scriptExecutionContext(); }

    JSDOMWindow& domWindow() const;

protected:
    JSDOMObject(JSC::Structure* structure, JSC::JSGlobalObject& globalObject)
        : Base(globalObject.vm(), structure)
    {
        ASSERT(scriptExecutionContext());
    }
};

template<typename ImplementationClass> class JSDOMWrapper : public JSDOMObject {
public:
    typedef JSDOMObject Base;
    typedef ImplementationClass DOMWrapped;
    static constexpr bool isDOMWrapper = true;

    ImplementationClass& wrapped() const { return const_cast<ImplementationClass&>(m_wrapped.get()); }
    static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSDOMWrapper<ImplementationClass>, m_wrapped); }

protected:
    JSDOMWrapper(JSC::Structure* structure, JSC::JSGlobalObject& globalObject, Ref<ImplementationClass>&& impl)
        : Base(structure, globalObject)
        , m_wrapped(WTFMove(impl)) { }

private:
    Ref<ImplementationClass> m_wrapped;
};

template<typename ImplementationClass> struct JSDOMWrapperConverterTraits;

template<typename JSClass, typename Enable = void>
struct JSDOMObjectInspector {
public:
    static constexpr bool isSimpleWrapper = false;
    static constexpr bool isComplexWrapper = false;
    static constexpr bool isBuiltin = true;
};

template<typename JSClass>
struct JSDOMObjectInspector<JSClass, typename std::enable_if<JSClass::isDOMWrapper>::type> {
private:
    template<typename T> static constexpr auto test(int) -> decltype(T::create(), bool()) { return true; }
    template<typename T> static constexpr bool test(...) { return false; }

public:
    static constexpr bool isSimpleWrapper = test<typename JSClass::DOMWrapped>(0);
    static constexpr bool isComplexWrapper = !isSimpleWrapper;
    static constexpr bool isBuiltin = false;
};

} // namespace WebCore
