#import "./html_utils.typ": add-tag-in-head
#import "./states.typ": (
    state-use-pyscript,
    state-pyscript-version,
    state-pyscript-data-list,
    state-pyscript-interpreters,
    state-pyscript-default-interpreter,
    state-pyscript-canvas-ids,
    current-page-label,
)

/// Define data needed to load a version of pyscript
#let pyscript-data(
  /// Url to `core.js`
  core-js-url,
  /// Additionnal tags to add to <head>, like mini-coi of core.css
  additionnal-head-tags: {},
) = (
  core-js-url: core-js-url,
  additionnal-head-tags: additionnal-head-tags
)

#let get-pep723(script) = {
  script.find(regex(
    //"(?m)^# /// (?P<type>[a-zA-Z0-9-]+)$\s(?P<content>(^#(| .*)$\s)+)^# ///$"
    "(?m)^# /// script$\s(?P<content>(^#(| .*)$\s)+)^# ///$"
  ))
}
#let parse-pep723(script) = {
  let metadata-section = get-pep723(script)
  if metadata-section == none {
    return none
  }
  let metadata-section = metadata-section.trim(
    "# /// script\n"
  ).trim(
    "# ///"
  ).replace(regex("(?m)^#(| )"), "")
  toml(bytes(metadata-section))
}

// TODO DOCUMENT THIS!

#let pyscript-show(it) = {
  let metadata = parse-pep723(it.text)
  if metadata == none {
    metadata = (:)
  }
  state-use-pyscript.update(x => true)
  let config = metadata.at("tool", default: (:)).at("pyscript", default: (:))

  let pyscript-config = (:)
  // Package dependencies
  if "dependencies" in metadata {
    pyscript-config.insert("packages", metadata.at("dependencies"))
  }
  // Files stetup
  if "files" in config {
    pyscript-config.insert("files", config.at("files"))
  }
  // Interpreteur selection
  if "interpreter" in config {
    pyscript-config.insert("interpreter", config.at("interpreter"))
  } else if state-pyscript-default-interpreter.final() != none {
    assert(
      state-pyscript-default-interpreter.final() in state-pyscript-interpreters.final(),
      message: state-pyscript-default-interpreter.final() + " is not in pyscript-interpreters",
    )
    pyscript-config.insert("interpreter", state-pyscript-interpreters.final().at(state-pyscript-default-interpreter.final()))
  }

  let attrs = (
    type: "py"
  )
  let default-val-terminal = true
  let default-val-worker = true
  let default-val-canvas = none
  if config.at("pygame", default: false) {
    default-val-terminal = false
    default-val-worker = false
    default-val-canvas = "canvas"
  }
  if config.at("terminal", default: default-val-terminal) {
    attrs.insert("terminal", "")
  }
  if config.at("worker", default: default-val-worker) {
    attrs.insert("worker", "")
  }
  let canvas-attr = config.at("canvas", default: default-val-canvas)
  if canvas-attr == false {
    canvas-attr = none
  }
  if canvas-attr == true {
    canvas-attr = "canvas"
  }
  if canvas-attr != none {
    attrs.insert("canvas", canvas-attr)
    
    assert(
      canvas-attr not in state-pyscript-canvas-ids.at(here()), 
      message: (
        "Can not have multiple canvas with the same name. Note that SDL2 has issues working with canvas",
        "with an id different than 'canvas', meaning that it is unadvised to have more than one script",
        "using SDL2 by page.",
        "(tool.pyscript.pygame = true set the default value for the SDL2 canvas to 'canvas' instead of none)"
      ).join(" ")
    )
    state-pyscript-canvas-ids.update(canvas-ids => canvas-ids + (canvas-attr,))
  }

  if pyscript-config != (:) {
    attrs.insert("config", json.encode(pyscript-config))
  }

  let script = it.text;
  if config.at("repl", default: false) {
    script = "import code\n" + script + "\ncode.interact(banner='', local=globals())"
  }
  let displayed-code = it.text;
  if config.at("hide-meta", default: false) {
    displayed-code = displayed-code.replace(get-pep723(displayed-code), "").trim("\n")
  }
  
  if not config.at("hide-code", default: false) {
    raw(
      displayed-code,
      block: true,
      lang: "python",
      align: it.align,
      syntaxes: it.syntaxes,
      theme: it.theme,
      tab-size: it.tab-size,
    )
  }

  html.elem(
    "script", 
    attrs: attrs,
    script
  )
  if canvas-attr != none {
    html.elem("canvas", attrs: ("id": canvas-attr))

    let page-label = current-page-label.at(here())
    let end-page-label = label(str(page-label) + "-end")
    let core-js-url = state-pyscript-data-list.at(end-page-label).at(state-pyscript-version.at(end-page-label)).core-js-url
    add-tag-in-head(
      html.script(
        type: "module",
        ```
        import { hooks } from "<CORE-JS-URL>";
        hooks.main.onReady.add((wrap, script) => {
          if (script.hasAttribute("canvas")) {
            const target = script.getAttribute("canvas");
            const canvas = document.getElementById(target);
            wrap.interpreter.canvas.setCanvas2D(canvas);
          }
        });
        ```.text.replace("<CORE-JS-URL>", core-js-url)
      )
    )
  }
}
    // also need pyscript hook to link canvas to pyodide:
    //
//        <script type="module">
//          // Pyscrypt has a py-game type that handle this, but it forces the interpreter to be
//          // from the cdn, which is quite meh.
//          // So I do the setup manually (https://docs.pyscript.net/2026.3.1/user-guide/pygame-ce/)
//          import { hooks } from "./pyscript/core.js";
//	  hooks.main.onReady.add((wrap, script) => {
//	    if (script.hasAttribute("canvas")) {
//	      const target = script.getAttribute("canvas");
//	      const canvas = document.getElementById(target);
//	      wrap.interpreter.canvas.setCanvas2D(canvas);
//	    }
//	  });
//	</script>
  //raw(block: true, lang: "json", json.encode(metadata))
