#pragma once

#include <AK/Optional.h>
#include <AK/String.h>
#include <LibJS/Forward.h>
#include <LibJS/Runtime/NativeFunction.h>
#include <LibJS/Runtime/Object.h>
#include <LibJS/Runtime/Value.h>

namespace Web::Bindings {

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

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

private:
    JS_DECLARE_NATIVE_FUNCTION(escape);
    JS_DECLARE_NATIVE_FUNCTION(supports);
    JS_DECLARE_NATIVE_FUNCTION(supports0);
    JS_DECLARE_NATIVE_FUNCTION(supports1);
    JS_DECLARE_NATIVE_FUNCTION(register_property);
    JS_DECLARE_NATIVE_FUNCTION(number);
    JS_DECLARE_NATIVE_FUNCTION(percent);
    JS_DECLARE_NATIVE_FUNCTION(deg);
    JS_DECLARE_NATIVE_FUNCTION(grad);
    JS_DECLARE_NATIVE_FUNCTION(rad);
    JS_DECLARE_NATIVE_FUNCTION(turn);
    JS_DECLARE_NATIVE_FUNCTION(fr);
    JS_DECLARE_NATIVE_FUNCTION(hz);
    JS_DECLARE_NATIVE_FUNCTION(k_hz);
    JS_DECLARE_NATIVE_FUNCTION(cap);
    JS_DECLARE_NATIVE_FUNCTION(ch);
    JS_DECLARE_NATIVE_FUNCTION(cm);
    JS_DECLARE_NATIVE_FUNCTION(cqb);
    JS_DECLARE_NATIVE_FUNCTION(cqh);
    JS_DECLARE_NATIVE_FUNCTION(cqi);
    JS_DECLARE_NATIVE_FUNCTION(cqmax);
    JS_DECLARE_NATIVE_FUNCTION(cqmin);
    JS_DECLARE_NATIVE_FUNCTION(cqw);
    JS_DECLARE_NATIVE_FUNCTION(dvb);
    JS_DECLARE_NATIVE_FUNCTION(dvh);
    JS_DECLARE_NATIVE_FUNCTION(dvi);
    JS_DECLARE_NATIVE_FUNCTION(dvmax);
    JS_DECLARE_NATIVE_FUNCTION(dvmin);
    JS_DECLARE_NATIVE_FUNCTION(dvw);
    JS_DECLARE_NATIVE_FUNCTION(em);
    JS_DECLARE_NATIVE_FUNCTION(ex);
    JS_DECLARE_NATIVE_FUNCTION(ic);
    JS_DECLARE_NATIVE_FUNCTION(in);
    JS_DECLARE_NATIVE_FUNCTION(lh);
    JS_DECLARE_NATIVE_FUNCTION(lvb);
    JS_DECLARE_NATIVE_FUNCTION(lvh);
    JS_DECLARE_NATIVE_FUNCTION(lvi);
    JS_DECLARE_NATIVE_FUNCTION(lvmax);
    JS_DECLARE_NATIVE_FUNCTION(lvmin);
    JS_DECLARE_NATIVE_FUNCTION(lvw);
    JS_DECLARE_NATIVE_FUNCTION(mm);
    JS_DECLARE_NATIVE_FUNCTION(pc);
    JS_DECLARE_NATIVE_FUNCTION(pt);
    JS_DECLARE_NATIVE_FUNCTION(px);
    JS_DECLARE_NATIVE_FUNCTION(q);
    JS_DECLARE_NATIVE_FUNCTION(rcap);
    JS_DECLARE_NATIVE_FUNCTION(rch);
    JS_DECLARE_NATIVE_FUNCTION(rem);
    JS_DECLARE_NATIVE_FUNCTION(rex);
    JS_DECLARE_NATIVE_FUNCTION(ric);
    JS_DECLARE_NATIVE_FUNCTION(rlh);
    JS_DECLARE_NATIVE_FUNCTION(svb);
    JS_DECLARE_NATIVE_FUNCTION(svh);
    JS_DECLARE_NATIVE_FUNCTION(svi);
    JS_DECLARE_NATIVE_FUNCTION(svmax);
    JS_DECLARE_NATIVE_FUNCTION(svmin);
    JS_DECLARE_NATIVE_FUNCTION(svw);
    JS_DECLARE_NATIVE_FUNCTION(vb);
    JS_DECLARE_NATIVE_FUNCTION(vh);
    JS_DECLARE_NATIVE_FUNCTION(vi);
    JS_DECLARE_NATIVE_FUNCTION(vmax);
    JS_DECLARE_NATIVE_FUNCTION(vmin);
    JS_DECLARE_NATIVE_FUNCTION(vw);
    JS_DECLARE_NATIVE_FUNCTION(dpcm);
    JS_DECLARE_NATIVE_FUNCTION(dpi);
    JS_DECLARE_NATIVE_FUNCTION(dppx);
    JS_DECLARE_NATIVE_FUNCTION(x);
    JS_DECLARE_NATIVE_FUNCTION(ms);
    JS_DECLARE_NATIVE_FUNCTION(s);
};

struct PropertyDefinition {
    bool inherits;
    Optional<String> initial_value {};
    String name;
    String syntax { "*"_string };
};

JS::ThrowCompletionOr<PropertyDefinition> convert_to_idl_value_for_property_definition(JS::VM&, JS::Value);

} // namespace Web::Bindings
