#pragma once

#include <AK/Utf16String.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>

namespace Web::Bindings {

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

private:
};

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

private:
    JS_DECLARE_NATIVE_FUNCTION(error_getter);
    JS_DECLARE_NATIVE_FUNCTION(src_getter);
    JS_DECLARE_NATIVE_FUNCTION(src_setter);
    JS_DECLARE_NATIVE_FUNCTION(src_object_getter);
    JS_DECLARE_NATIVE_FUNCTION(src_object_setter);
    JS_DECLARE_NATIVE_FUNCTION(current_src_getter);
    JS_DECLARE_NATIVE_FUNCTION(cross_origin_getter);
    JS_DECLARE_NATIVE_FUNCTION(cross_origin_setter);
    JS_DECLARE_NATIVE_FUNCTION(network_state_getter);
    JS_DECLARE_NATIVE_FUNCTION(preload_getter);
    JS_DECLARE_NATIVE_FUNCTION(preload_setter);
    JS_DECLARE_NATIVE_FUNCTION(buffered_getter);
    JS_DECLARE_NATIVE_FUNCTION(ready_state_getter);
    JS_DECLARE_NATIVE_FUNCTION(seeking_getter);
    JS_DECLARE_NATIVE_FUNCTION(current_time_getter);
    JS_DECLARE_NATIVE_FUNCTION(current_time_setter);
    JS_DECLARE_NATIVE_FUNCTION(duration_getter);
    JS_DECLARE_NATIVE_FUNCTION(paused_getter);
    JS_DECLARE_NATIVE_FUNCTION(default_playback_rate_getter);
    JS_DECLARE_NATIVE_FUNCTION(default_playback_rate_setter);
    JS_DECLARE_NATIVE_FUNCTION(playback_rate_getter);
    JS_DECLARE_NATIVE_FUNCTION(playback_rate_setter);
    JS_DECLARE_NATIVE_FUNCTION(played_getter);
    JS_DECLARE_NATIVE_FUNCTION(seekable_getter);
    JS_DECLARE_NATIVE_FUNCTION(ended_getter);
    JS_DECLARE_NATIVE_FUNCTION(autoplay_getter);
    JS_DECLARE_NATIVE_FUNCTION(autoplay_setter);
    JS_DECLARE_NATIVE_FUNCTION(loop_getter);
    JS_DECLARE_NATIVE_FUNCTION(loop_setter);
    JS_DECLARE_NATIVE_FUNCTION(controls_getter);
    JS_DECLARE_NATIVE_FUNCTION(controls_setter);
    JS_DECLARE_NATIVE_FUNCTION(volume_getter);
    JS_DECLARE_NATIVE_FUNCTION(volume_setter);
    JS_DECLARE_NATIVE_FUNCTION(muted_getter);
    JS_DECLARE_NATIVE_FUNCTION(muted_setter);
    JS_DECLARE_NATIVE_FUNCTION(default_muted_getter);
    JS_DECLARE_NATIVE_FUNCTION(default_muted_setter);
    JS_DECLARE_NATIVE_FUNCTION(audio_tracks_getter);
    JS_DECLARE_NATIVE_FUNCTION(video_tracks_getter);
    JS_DECLARE_NATIVE_FUNCTION(text_tracks_getter);
    JS_DECLARE_NATIVE_FUNCTION(load);
    JS_DECLARE_NATIVE_FUNCTION(can_play_type);
    JS_DECLARE_NATIVE_FUNCTION(fast_seek);
    JS_DECLARE_NATIVE_FUNCTION(get_start_date);
    JS_DECLARE_NATIVE_FUNCTION(play);
    JS_DECLARE_NATIVE_FUNCTION(pause);
    JS_DECLARE_NATIVE_FUNCTION(add_text_track);
};

enum class Preload : u8 {
    Auto,
    None,
    Metadata,
};

JS::ThrowCompletionOr<Preload> convert_to_idl_value_for_preload(JS::VM&, JS::Value);

Utf16String idl_enum_to_string(Preload);

enum class CanPlayTypeResult : u8 {
    Empty,
    Maybe,
    Probably,
};

JS::ThrowCompletionOr<CanPlayTypeResult> convert_to_idl_value_for_can_play_type_result(JS::VM&, JS::Value);

Utf16String idl_enum_to_string(CanPlayTypeResult);

} // namespace Web::Bindings
