///|
priv struct TagInfo {
  fn_name : String
  named_params : Map[String, String]
}

///|
let void_elements : Set[String] = Set::from_array([
  "area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "param",
  "source", "track", "wbr",
])

///|
fn is_void_element(tag : String) -> Bool {
  void_elements.contains(tag)
}

///|
let common_params : Map[String, String] = {
  "style": "style",
  "id": "id",
  "class": "class",
  "title": "title",
  "hidden": "hidden",
}

///|
let tag_info_cache : Map[String, TagInfo] = {
  "div": {
    fn_name: "div",
    named_params: common_params.merge({
      "on_click": "on_click",
      "on_mousedown": "on_mousedown",
      "on_mouseup": "on_mouseup",
      "on_scroll": "on_scroll",
      "on_keydown": "on_keydown",
      "on_keyup": "on_keyup",
    }),
  },
  "p": { fn_name: "p", named_params: common_params },
  "span": { fn_name: "span", named_params: common_params },
  "a": {
    fn_name: "a",
    named_params: common_params.merge({
      "href": "href",
      "target": "target",
      "rel": "rel",
      "download": "download",
    }),
  },
  "button": {
    fn_name: "button",
    named_params: common_params.merge({
      "type": "type_",
      "disabled": "disabled",
      "name": "name",
      "value": "value",
      "autofocus": "autofocus",
      "on_click": "on_click",
    }),
  },
  "h1": { fn_name: "h1", named_params: common_params.merge({ "cite": "cite" }) },
  "h2": { fn_name: "h2", named_params: common_params },
  "h3": { fn_name: "h3", named_params: common_params },
  "h4": { fn_name: "h4", named_params: common_params },
  "h5": { fn_name: "h5", named_params: common_params },
  "h6": { fn_name: "h6", named_params: common_params },
  "ul": {
    fn_name: "ul",
    named_params: common_params.merge({ "on_click": "on_click" }),
  },
  "ol": {
    fn_name: "ol",
    named_params: common_params.merge({
      "reversed": "reversed",
      "start": "start",
    }),
  },
  "li": {
    fn_name: "li",
    named_params: common_params.merge({
      "value": "value",
      "on_click": "on_click",
    }),
  },
  "dl": { fn_name: "dl", named_params: common_params },
  "dt": { fn_name: "dt", named_params: common_params },
  "dd": { fn_name: "dd", named_params: common_params },
  "img": {
    fn_name: "img",
    named_params: common_params.merge({
      "src": "src",
      "alt": "alt",
      "width": "width",
      "height": "height",
      "srcset": "srcset",
      "sizes": "sizes",
      "loading": "loading",
      "decoding": "decoding",
    }),
  },
  "form": {
    fn_name: "form",
    named_params: common_params.merge({
      "action": "action",
      "name": "name",
      "on_submit": "on_submit",
    }),
  },
  "input": {
    fn_name: "input",
    named_params: common_params.merge({
      "type": "input_type",
      "name": "name",
      "value": "value",
      "checked": "checked",
      "placeholder": "placeholder",
      "disabled": "disabled",
      "readonly": "read_only",
      "multiple": "multiple",
      "accept": "accept",
      "max": "max",
      "min": "min",
      "step": "step",
      "maxlength": "maxlength",
      "minlength": "minlength",
      "pattern": "pattern",
      "size": "size",
      "required": "required",
      "autofocus": "autofocus",
      "list": "list",
      "inputmode": "inputmode",
    }),
  },
  "textarea": {
    fn_name: "textarea",
    named_params: common_params.merge({
      "name": "name",
      "value": "value",
      "rows": "rows",
      "cols": "cols",
      "placeholder": "placeholder",
      "readonly": "read_only",
      "disabled": "disabled",
      "maxlength": "maxlength",
      "minlength": "minlength",
      "required": "required",
      "autofocus": "autofocus",
      "wrap": "wrap",
    }),
  },
  "select": {
    fn_name: "select",
    named_params: common_params.merge({
      "disabled": "disabled",
      "name": "name",
      "multiple": "multiple",
      "size": "size",
      "required": "required",
      "autofocus": "autofocus",
    }),
  },
  "option": {
    fn_name: "option",
    named_params: common_params.merge({
      "label": "label",
      "disabled": "disabled",
      "value": "value",
      "selected": "selected",
    }),
  },
  "optgroup": {
    fn_name: "optgroup",
    named_params: common_params.merge({
      "label": "label",
      "disabled": "disabled",
    }),
  },
  "label": {
    fn_name: "label",
    named_params: common_params.merge({ "for": "for_" }),
  },
  "table": { fn_name: "table", named_params: common_params },
  "caption": { fn_name: "caption", named_params: common_params },
  "thead": { fn_name: "thead", named_params: common_params },
  "tbody": { fn_name: "tbody", named_params: common_params },
  "tfoot": { fn_name: "tfoot", named_params: common_params },
  "tr": { fn_name: "tr", named_params: common_params },
  "td": {
    fn_name: "td",
    named_params: common_params.merge({
      "colspan": "colspan",
      "rowspan": "rowspan",
      "headers": "headers",
    }),
  },
  "th": {
    fn_name: "th",
    named_params: common_params.merge({
      "abbr": "abbr",
      "colspan": "colspan",
      "rowspan": "rowspan",
      "headers": "headers",
      "scope": "scope",
    }),
  },
  "col": {
    fn_name: "col",
    named_params: common_params.merge({ "span": "span" }),
  },
  "colgroup": {
    fn_name: "colgroup",
    named_params: common_params.merge({ "span": "span" }),
  },
  "br": { fn_name: "br", named_params: common_params },
  "hr": { fn_name: "hr", named_params: common_params },
  "pre": { fn_name: "pre", named_params: common_params },
  "blockquote": { fn_name: "blockquote", named_params: common_params },
  "section": { fn_name: "section", named_params: common_params },
  "header": { fn_name: "header", named_params: common_params },
  "footer": { fn_name: "footer", named_params: common_params },
  "nav": { fn_name: "nav", named_params: common_params },
  "main": { fn_name: "main_", named_params: common_params },
  "article": { fn_name: "article", named_params: common_params },
  "aside": { fn_name: "aside", named_params: common_params },
  "figure": { fn_name: "figure", named_params: common_params },
  "figcaption": { fn_name: "figcaption", named_params: common_params },
  "details": {
    fn_name: "details",
    named_params: common_params.merge({ "open": "open" }),
  },
  "summary": { fn_name: "summary", named_params: common_params },
  "small": { fn_name: "small", named_params: common_params },
  "mark": { fn_name: "mark", named_params: common_params },
  "del": { fn_name: "del", named_params: common_params },
  "ins": { fn_name: "ins", named_params: common_params },
  "s": { fn_name: "s", named_params: common_params },
  "cite": { fn_name: "cite", named_params: common_params },
  "q": { fn_name: "q", named_params: common_params },
  "abbr": {
    fn_name: "abbr",
    named_params: common_params.merge({ "for": "for_" }),
  },
  "kbd": { fn_name: "kbd", named_params: common_params },
  "samp": { fn_name: "samp", named_params: common_params },
  "var": { fn_name: "var_", named_params: common_params },
  "time": {
    fn_name: "time",
    named_params: common_params.merge({ "datetime": "datetime" }),
  },
  "address": { fn_name: "address", named_params: common_params },
  "code": { fn_name: "code", named_params: common_params },
  "em": { fn_name: "em", named_params: common_params },
  "strong": { fn_name: "strong", named_params: common_params },
  "i": { fn_name: "i", named_params: common_params },
  "b": { fn_name: "b", named_params: common_params },
  "u": { fn_name: "u", named_params: common_params },
  "sub": { fn_name: "sub", named_params: common_params },
  "sup": { fn_name: "sup", named_params: common_params },
  "iframe": {
    fn_name: "iframe",
    named_params: common_params.merge({
      "src": "src",
      "width": "width",
      "height": "height",
      "loading": "loading",
      "allow": "allow",
      "sandbox": "sandbox",
      "allowfullscreen": "allowfullscreen",
    }),
  },
  "base": {
    fn_name: "base",
    named_params: common_params.merge({ "href": "href", "target": "target" }),
  },
  "meta": {
    fn_name: "meta",
    named_params: common_params.merge({
      "charset": "charset",
      "name": "name",
      "content": "content",
      "http-equiv": "http_equiv",
    }),
  },
  "link": {
    fn_name: "link",
    named_params: common_params.merge({
      "href": "href",
      "rel": "rel",
      "type": "type_",
      "media": "media",
      "sizes": "sizes",
    }),
  },
  "style": { fn_name: "style_tag", named_params: common_params },
  "script": {
    fn_name: "script",
    named_params: common_params.merge({
      "src": "src",
      "type": "type_",
      "async": "async_",
      "defer": "defer_",
    }),
  },
  "noscript": { fn_name: "noscript", named_params: common_params },
  "template": { fn_name: "template", named_params: common_params },
  "slot": { fn_name: "slot", named_params: common_params },
  "data": { fn_name: "data", named_params: common_params },
  "dfn": { fn_name: "dfn", named_params: common_params },
  "bdi": { fn_name: "bdi", named_params: common_params },
  "bdo": { fn_name: "bdo", named_params: common_params },
  "ruby": { fn_name: "ruby", named_params: common_params },
  "rt": { fn_name: "rt", named_params: common_params },
  "rp": { fn_name: "rp", named_params: common_params },
  "wbr": { fn_name: "wbr", named_params: common_params },
  "hgroup": { fn_name: "hgroup", named_params: common_params },
  "menu": { fn_name: "menu", named_params: common_params },
  "canvas": {
    fn_name: "canvas",
    named_params: common_params.merge({
      "on_mousedown": "on_mousedown",
      "on_mouseup": "on_mouseup",
      "on_scroll": "on_scroll",
      "on_keydown": "on_keydown",
      "on_keyup": "on_keyup",
    }),
  },
  "progress": {
    fn_name: "progress",
    named_params: common_params.merge({ "value": "value", "max": "max" }),
  },
  "meter": {
    fn_name: "meter",
    named_params: common_params.merge({
      "value": "value",
      "min": "min",
      "max": "max",
      "low": "low",
      "high": "high",
      "optimum": "optimum",
    }),
  },
  "output": {
    fn_name: "output",
    named_params: common_params.merge({ "name": "name", "for": "for_" }),
  },
  "fieldset": {
    fn_name: "fieldset",
    named_params: common_params.merge({ "disabled": "disabled", "name": "name" }),
  },
  "legend": { fn_name: "legend", named_params: common_params },
  "datalist": { fn_name: "datalist", named_params: common_params },
  "dialog": {
    fn_name: "dialog",
    named_params: common_params.merge({
      "open": "open",
      "on_close": "on_close",
      "on_cancel": "on_cancel",
    }),
  },
  "audio": {
    fn_name: "audio",
    named_params: common_params.merge({
      "src": "src",
      "controls": "controls",
      "autoplay": "autoplay",
      "loop": "loop_",
      "muted": "muted",
      "preload": "preload",
    }),
  },
  "video": {
    fn_name: "video",
    named_params: common_params.merge({
      "src": "src",
      "controls": "controls",
      "autoplay": "autoplay",
      "loop": "loop_",
      "muted": "muted",
      "preload": "preload",
      "poster": "poster",
    }),
  },
  "map": {
    fn_name: "map",
    named_params: common_params.merge({ "name": "name" }),
  },
  "area": {
    fn_name: "area",
    named_params: common_params.merge({
      "alt": "alt",
      "coords": "coords",
      "shape": "shape",
      "href": "href",
      "target": "target",
    }),
  },
  "source": {
    fn_name: "source",
    named_params: common_params.merge({
      "src": "src",
      "srcset": "srcset",
      "media": "media",
      "type": "type_",
      "sizes": "sizes",
    }),
  },
  "track": {
    fn_name: "track",
    named_params: common_params.merge({
      "kind": "kind",
      "srclang": "srclang",
      "label": "label",
      "default": "default",
      "src": "src",
    }),
  },
  "embed": { fn_name: "embed", named_params: common_params },
  "object": { fn_name: "object", named_params: common_params },
  "search": { fn_name: "search", named_params: common_params },
  "html": {
    fn_name: "html",
    named_params: common_params.merge({ "lang": "lang", "dir": "dir" }),
  },
  "head": { fn_name: "head", named_params: common_params },
  "body": {
    fn_name: "body",
    named_params: common_params.merge({
      "lang": "lang",
      "dir": "dir",
      "on_scroll": "on_scroll",
      "on_keydown": "on_keydown",
      "on_keyup": "on_keyup",
    }),
  },
  "title": { fn_name: "title", named_params: common_params },
  "picture": { fn_name: "picture", named_params: common_params },
}

///|
fn get_tag_info(tag : String) -> TagInfo? {
  tag_info_cache.get(tag)
}