{ buildPythonApplication
, fetchFromGitHub
, writeShellScript
, lib
, python

, bsdiff4
, certifi
, colorama
, cymem
, cython
, jellyfish
, jinja2
, kivy
, platformdirs
, pyyaml
, schema
, websockets

, enabledWorlds ? [ "generic" "factorio" ]

# factorio
, factorio-rcon-py

, withWebHostLib ? true
, flask
, pony
, waitress
, flask-caching
, flask-compress
, flask-limiter
, bokeh
, markupsafe
}:

let
  worldEnabled = worldName: lib.any (x: x == worldName) enabledWorlds;
in
buildPythonApplication rec {
  pname = "archipelago";
  version = "0.5.0";

  src = fetchFromGitHub {
    owner = "ArchipelagoMW";
    repo = "Archipelago";
    rev = version;
    hash = "sha256-I6UHojEpC2/9bYK1khN1r+KsBTmU6zdsW8tpCYtB51I=";
  };

  propagatedBuildInputs = [
    bsdiff4
    certifi
    colorama
    cymem
    cython
    jellyfish
    jinja2
    kivy
    platformdirs
    pyyaml
    schema
    websockets
  ] ++ (lib.optionals (worldEnabled "factorio") [
    factorio-rcon-py
  ]) ++ (lib.optionals withWebHostLib [
    flask
    pony
    waitress
    flask-caching
    flask-compress
    flask-limiter
    bokeh
    markupsafe
  ]);

  format = "other";
  postPatch = ''
    # Disable ModuleUpdate; we're effectively frozen.
    sed -i 's,^update_ran = .*,update_ran = True,' ModuleUpdate.py
  '';
  buildPhase = ''
    runHook preBuild

    install -d worlds_disabled
    for f in worlds/*; do
      test -d $f || continue
      worldName="$(basename $f)"
      [[ " ''${enabledWorlds[@]} " =~ " ''${worldName} " ]] && continue
      echo "Disabling $worldName - not explicitly enabled" >&2
      mv worlds/$worldName worlds_disabled/$worldName
    done

    runHook postBuild
  '';
  inherit enabledWorlds;
  __structuredAttrs = true;
  installPhase = ''
    runHook preInstall

    export INSTALLDIR=$out/${python.sitePackages}/archipelago
    install -d $INSTALLDIR
    cp -R ./ -t $INSTALLDIR

    mkdir $out/bin

    makeEntrypoint() {
      local name="$1"
      local module="$2"

      cat <<EOF >$out/bin/$1
    #!/bin/sh
    export PYTHONPATH=$PYTHONPATH:$out/${python.sitePackages}:$INSTALLDIR
    exec ${python}/bin/python -m "$2" "\$@"
    EOF
      chmod +x $out/bin/$1
    }

    ${lib.optionalString (worldEnabled "factorio") "makeEntrypoint archipelago-factorio archipelago.FactorioClient"}
    makeEntrypoint archipelago-generate archipelago.Generate
    makeEntrypoint archipelago-multiserver archipelago.MultiServer
    makeEntrypoint archipelago-webhost archipelago.WebHost
    makeEntrypoint archipelago-launcher archipelago.Launcher

    install -d $INSTALLDIR/Players
    install -d $INSTALLDIR/data/sprites
    echo '{}' > $INSTALLDIR/manifest.json

    runHook postInstall
  '';

  passthru = {
    inherit factorio-rcon-py;
  };
}