#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 HTMLFormElementConstructor {
public:
    static void initialize(JS::Realm&, JS::NativeFunction&);
    static JS::ThrowCompletionOr<GC::Ref<JS::Object>> construct(InterfaceConstructor&, JS::FunctionObject&);

private:
};

class HTMLFormElementPrototype : public JS::Object {
    JS_OBJECT(HTMLFormElementPrototype, JS::Object);
    GC_DECLARE_ALLOCATOR(HTMLFormElementPrototype);

public:
    static void define_unforgeable_attributes(JS::Realm&, JS::Object&);

    explicit HTMLFormElementPrototype(JS::Realm&);
    virtual void initialize(JS::Realm&) override;
    virtual ~HTMLFormElementPrototype() override;

private:
    JS_DECLARE_NATIVE_FUNCTION(accept_charset_getter);
    JS_DECLARE_NATIVE_FUNCTION(accept_charset_setter);
    JS_DECLARE_NATIVE_FUNCTION(action_getter);
    JS_DECLARE_NATIVE_FUNCTION(action_setter);
    JS_DECLARE_NATIVE_FUNCTION(autocomplete_getter);
    JS_DECLARE_NATIVE_FUNCTION(autocomplete_setter);
    JS_DECLARE_NATIVE_FUNCTION(enctype_getter);
    JS_DECLARE_NATIVE_FUNCTION(enctype_setter);
    JS_DECLARE_NATIVE_FUNCTION(encoding_getter);
    JS_DECLARE_NATIVE_FUNCTION(encoding_setter);
    JS_DECLARE_NATIVE_FUNCTION(method_getter);
    JS_DECLARE_NATIVE_FUNCTION(method_setter);
    JS_DECLARE_NATIVE_FUNCTION(name_getter);
    JS_DECLARE_NATIVE_FUNCTION(name_setter);
    JS_DECLARE_NATIVE_FUNCTION(no_validate_getter);
    JS_DECLARE_NATIVE_FUNCTION(no_validate_setter);
    JS_DECLARE_NATIVE_FUNCTION(target_getter);
    JS_DECLARE_NATIVE_FUNCTION(target_setter);
    JS_DECLARE_NATIVE_FUNCTION(rel_getter);
    JS_DECLARE_NATIVE_FUNCTION(rel_setter);
    JS_DECLARE_NATIVE_FUNCTION(rel_list_getter);
    JS_DECLARE_NATIVE_FUNCTION(rel_list_setter);
    JS_DECLARE_NATIVE_FUNCTION(elements_getter);
    JS_DECLARE_NATIVE_FUNCTION(length_getter);
    JS_DECLARE_NATIVE_FUNCTION(submit);
    JS_DECLARE_NATIVE_FUNCTION(request_submit);
    JS_DECLARE_NATIVE_FUNCTION(reset);
    JS_DECLARE_NATIVE_FUNCTION(check_validity);
    JS_DECLARE_NATIVE_FUNCTION(report_validity);
};

enum class Autocomplete : u8 {
    On,
    Off,
};

JS::ThrowCompletionOr<Autocomplete> convert_to_idl_value_for_autocomplete(JS::VM&, JS::Value);

Utf16String idl_enum_to_string(Autocomplete);

enum class EnctypeAttribute : u8 {
    Application_XWwwFormUrlencoded,
    Multipart_FormData,
    Text_Plain,
};

JS::ThrowCompletionOr<EnctypeAttribute> convert_to_idl_value_for_enctype_attribute(JS::VM&, JS::Value);

Utf16String idl_enum_to_string(EnctypeAttribute);

enum class MethodAttribute : u8 {
    Get,
    Post,
    Dialog,
};

JS::ThrowCompletionOr<MethodAttribute> convert_to_idl_value_for_method_attribute(JS::VM&, JS::Value);

Utf16String idl_enum_to_string(MethodAttribute);

enum class FormEnctypeAttribute : u8 {
    Application_XWwwFormUrlencoded,
    Multipart_FormData,
    Text_Plain,
};

JS::ThrowCompletionOr<FormEnctypeAttribute> convert_to_idl_value_for_form_enctype_attribute(JS::VM&, JS::Value);

Utf16String idl_enum_to_string(FormEnctypeAttribute);

enum class FormMethodAttribute : u8 {
    Get,
    Post,
    Dialog,
};

JS::ThrowCompletionOr<FormMethodAttribute> convert_to_idl_value_for_form_method_attribute(JS::VM&, JS::Value);

Utf16String idl_enum_to_string(FormMethodAttribute);

enum class SelectionMode : u8 {
    Select,
    Start,
    End,
    Preserve,
};

JS::ThrowCompletionOr<SelectionMode> convert_to_idl_value_for_selection_mode(JS::VM&, JS::Value);

Utf16String idl_enum_to_string(SelectionMode);

} // namespace Web::Bindings
