/*
 * Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
 *
 * SPDX-License-Identifier: BSD-2-Clause
 */

#pragma once

#include <AK/Weakable.h>
#include <LibJS/Heap/GCPtr.h>
#include <LibJS/Runtime/Object.h>
#include <LibWeb/Forward.h>

namespace Web::Bindings {

#define WEB_PLATFORM_OBJECT(class_, base_class)                                         \
    JS_OBJECT(class_, base_class)                                                       \
    virtual bool implements_interface(DeprecatedString const& interface) const override \
    {                                                                                   \
        if (interface == #class_)                                                       \
            return true;                                                                \
        return Base::implements_interface(interface);                                   \
    }

// https://webidl.spec.whatwg.org/#dfn-platform-object
class PlatformObject
    : public JS::Object
    , public Weakable<PlatformObject> {
    JS_OBJECT(PlatformObject, JS::Object);

public:
    virtual ~PlatformObject() override;

    JS::Realm& realm() const;

    // FIXME: This should return a type that works in both window and worker contexts.
    HTML::Window& global_object() const;

    // https://webidl.spec.whatwg.org/#implements
    // This is implemented by overrides that get generated by the WEB_PLATFORM_OBJECT macro.
    [[nodiscard]] virtual bool implements_interface(DeprecatedString const&) const { return false; }

protected:
    explicit PlatformObject(JS::Realm&);
    explicit PlatformObject(JS::Object& prototype);
};

}
