#pragma once

#include <AK/Optional.h>
#include <AK/String.h>
#include <AK/Utf16String.h>
#include <AK/Vector.h>
#include <LibJS/Forward.h>
#include <LibJS/Runtime/NativeFunction.h>
#include <LibJS/Runtime/Object.h>
#include <LibJS/Runtime/Value.h>
#include <LibWeb/Bindings/InterfaceObject.h>
#include <LibWeb/WebIDL/Types.h>

namespace Web::Bindings {

struct NotificationConstructor {
public:
    static void initialize(JS::Realm&, JS::NativeFunction&);
    static JS::ThrowCompletionOr<GC::Ref<JS::Object>> construct(InterfaceConstructor&, JS::FunctionObject&);

private:
    JS_DECLARE_NATIVE_FUNCTION(max_actions_getter);
};

struct NotificationPrototype {
public:
    static void initialize(JS::Realm&, JS::Object&);
    static void define_unforgeable_attributes(JS::Realm&, JS::Object&);

private:
    JS_DECLARE_NATIVE_FUNCTION(title_getter);
    JS_DECLARE_NATIVE_FUNCTION(dir_getter);
    JS_DECLARE_NATIVE_FUNCTION(lang_getter);
    JS_DECLARE_NATIVE_FUNCTION(body_getter);
    JS_DECLARE_NATIVE_FUNCTION(navigate_getter);
    JS_DECLARE_NATIVE_FUNCTION(tag_getter);
    JS_DECLARE_NATIVE_FUNCTION(image_getter);
    JS_DECLARE_NATIVE_FUNCTION(icon_getter);
    JS_DECLARE_NATIVE_FUNCTION(badge_getter);
    JS_DECLARE_NATIVE_FUNCTION(timestamp_getter);
    JS_DECLARE_NATIVE_FUNCTION(renotify_getter);
    JS_DECLARE_NATIVE_FUNCTION(silent_getter);
    JS_DECLARE_NATIVE_FUNCTION(require_interaction_getter);
    JS_DECLARE_NATIVE_FUNCTION(data_getter);
    JS_DECLARE_NATIVE_FUNCTION(actions_getter);
};

enum class NotificationPermission : u8 {
    Default,
    Denied,
    Granted,
};

JS::ThrowCompletionOr<NotificationPermission> convert_to_idl_value_for_notification_permission(JS::VM&, JS::Value);

Utf16String idl_enum_to_string(NotificationPermission);

enum class NotificationDirection : u8 {
    Auto,
    Ltr,
    Rtl,
};

JS::ThrowCompletionOr<NotificationDirection> convert_to_idl_value_for_notification_direction(JS::VM&, JS::Value);

Utf16String idl_enum_to_string(NotificationDirection);

struct NotificationAction {
    String action;
    Optional<String> icon {};
    Optional<String> navigate {};
    String title;
};

JS::ThrowCompletionOr<NotificationAction> convert_to_idl_value_for_notification_action(JS::VM&, JS::Value);

struct NotificationOptions {
    Vector<NotificationAction> actions { Vector<NotificationAction> {} };
    Optional<String> badge {};
    String body { String {} };
    JS::Value data { JS::js_null() };
    NotificationDirection dir { NotificationDirection::Auto };
    Optional<String> icon {};
    Optional<String> image {};
    String lang { String {} };
    Optional<String> navigate {};
    bool renotify { false };
    bool require_interaction { false };
    Optional<bool> silent { OptionalNone {} };
    String tag { String {} };
    Optional<WebIDL::UnsignedLongLong> timestamp {};
};

JS::ThrowCompletionOr<NotificationOptions> convert_to_idl_value_for_notification_options(JS::VM&, JS::Value);

} // namespace Web::Bindings
